svn-id: r10333
This commit is contained in:
Torbjörn Andersson 2003-09-20 12:43:52 +00:00
parent f4861af4d2
commit 6539b8a0e6
11 changed files with 2569 additions and 3121 deletions

View file

@ -19,20 +19,18 @@
#include "stdafx.h" #include "stdafx.h"
#ifndef INSIDE_LINC // Are we running in linc?
#include "console.h" #include "console.h"
#endif
#include "driver/driver96.h" #include "driver/driver96.h"
#include "interpreter.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
// I assume Linc was the name of some sort of development tool. Anyway, I've
// removed the pieces of code that were labelled as INSIDE_LINC, because they
// didn't look easily portable.
// This file serves two purposes. It is compiled as part of the test functions // The machine code table
// of Linc, and also as part of the game
// The machine code table
int32 FN_test_function(int32 *params); int32 FN_test_function(int32 *params);
int32 FN_test_flags(int32 *params); int32 FN_test_flags(int32 *params);
@ -50,11 +48,11 @@ int32 FN_add_subject(int32 *);
int32 FN_interact(int32 *); int32 FN_interact(int32 *);
int32 FN_choose(int32 *); int32 FN_choose(int32 *);
int32 FN_walk(int32 *); int32 FN_walk(int32 *);
int32 FN_walk_to_anim(int32 *); // walk to start position of anim int32 FN_walk_to_anim(int32 *); // walk to start position of anim
int32 FN_turn(int32 *); // turn to (dir) int32 FN_turn(int32 *); // turn to (dir)
int32 FN_stand_at(int32 *); // stand at (x,y,dir) int32 FN_stand_at(int32 *); // stand at (x,y,dir)
int32 FN_stand(int32 *); // stand facing (dir) int32 FN_stand(int32 *); // stand facing (dir)
int32 FN_stand_after_anim(int32 *); // stand at end position of anim int32 FN_stand_after_anim(int32 *); // stand at end position of anim
int32 FN_pause(int32 *); int32 FN_pause(int32 *);
int32 FN_mega_table_anim(int32 *); int32 FN_mega_table_anim(int32 *);
int32 FN_add_menu_object(int32 *); int32 FN_add_menu_object(int32 *);
@ -154,16 +152,15 @@ int32 FN_change_shadows(int32 *params);
#define MAX_FN_NUMBER 117 #define MAX_FN_NUMBER 117
extern int32 (*McodeTable[])(int32 *); extern int32 (*McodeTable[]) (int32 *);
#ifndef INSIDE_LINC // Point to the global variable data
int32 * globalInterpreterVariables2 = NULL; // Point to the global varibale data int32 *globalInterpreterVariables2 = NULL;
int g_debugFlag = 0; // Set this to turn debugging on
#endif
int g_debugFlag = 0; // Set this to turn debugging on
int32 (*McodeTable[MAX_FN_NUMBER+1])(int32 *) = int32 (*McodeTable[MAX_FN_NUMBER + 1]) (int32 *) = {
{ FN_test_function, FN_test_function,
FN_test_flags, FN_test_flags,
FN_register_start_point, FN_register_start_point,
FN_init_background, FN_init_background,
@ -283,320 +280,276 @@ int32 (*McodeTable[MAX_FN_NUMBER+1])(int32 *) =
FN_change_shadows, FN_change_shadows,
}; };
#define CHECKSTACKPOINTER2 ASSERT((stackPointer2>=0)&&(stackPointer2<STACK_SIZE)); #define CHECKSTACKPOINTER2 ASSERT(stackPointer2 >= 0 && stackPointer2 < STACK_SIZE);
#define PUSHONSTACK(x) {stack2[stackPointer2] = (x);stackPointer2++;CHECKSTACKPOINTER2;} #define PUSHONSTACK(x) { stack2[stackPointer2] = (x); stackPointer2++; CHECKSTACKPOINTER2 }
#define POPOFFSTACK(x) {x=stack2[stackPointer2-1];stackPointer2--;CHECKSTACKPOINTER2;} #define POPOFFSTACK(x) { x = stack2[stackPointer2 - 1]; stackPointer2--; CHECKSTACKPOINTER2 }
#define DOOPERATION(x) {stack2[stackPointer2-2] = (x);stackPointer2--;CHECKSTACKPOINTER2;} #define DOOPERATION(x) { stack2[stackPointer2 - 2] = (x); stackPointer2--; CHECKSTACKPOINTER2 }
#ifndef INSIDE_LINC void SetGlobalInterpreterVariables(int32 *vars) {
void SetGlobalInterpreterVariables(int32 *vars)
{
globalInterpreterVariables2 = vars; globalInterpreterVariables2 = vars;
} }
#endif
#ifdef INSIDE_LINC // Are we running in linc? int RunScript(char *scriptData, char *objectData, uint32 *offset) {
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * objectData , uint32 *offset )
#else
int RunScript ( char * scriptData , char * objectData , uint32 *offset )
#endif
{
#define STACK_SIZE 10 #define STACK_SIZE 10
_standardHeader *header = (_standardHeader *)scriptData; _standardHeader *header = (_standardHeader *) scriptData;
scriptData += sizeof(_standardHeader) + sizeof(_object_hub); scriptData += sizeof(_standardHeader) + sizeof(_object_hub);
// The script data format: // The script data format:
// int32_TYPE 1 Size of variable space in bytes
// ... The variable space
// int32_TYPE 1 Size of variable space in bytes // int32_TYPE 1 numberOfScripts
// ... The variable space // int32_TYPE numberOfScripts The offsets for each script
// int32_TYPE 1 numberOfScripts
// int32_TYPE numberOfScripts The offsets for each script
// Initialise some stuff // Initialise some stuff
int ip = 0; // Code pointer int ip = 0; // Code pointer
int curCommand,parameter,value; // Command and parameter variables int curCommand,parameter, value; // Command and parameter variables
int32 stack2[STACK_SIZE]; // The current stack int32 stack2[STACK_SIZE]; // The current stack
int32 stackPointer2 = 0; // Position within stack int32 stackPointer2 = 0; // Position within stack
int parameterReturnedFromMcodeFunction=0; // Allow scripts to return things int parameterReturnedFromMcodeFunction = 0; // Allow scripts to return things
int savedStartOfMcode=0; // For saving start of mcode commands int savedStartOfMcode = 0; // For saving start of mcode commands
int count;
int retVal;
int caseCount, foundCase;
int scriptNumber, foundScript;
const char *tempScrPtr;
// Get the start of variables and start of code // Get the start of variables and start of code
DEBUG3("Enter interpreter data %x, object %x, offset %d",scriptData,objectData,*offset); DEBUG("Enter interpreter data %x, object %x, offset %d", scriptData, objectData, *offset);
// FIXME: 'scriptData' and 'variables' used to be const. However, // FIXME: 'scriptData' and 'variables' used to be const. However,
// this code writes into 'variables' so it can not be const. // this code writes into 'variables' so it can not be const.
char *variables = scriptData + sizeof(int); char *variables = scriptData + sizeof(int);
const char *code = scriptData + (int32)READ_LE_UINT32(scriptData) + sizeof(int); const char *code = scriptData + (int32) READ_LE_UINT32(scriptData) + sizeof(int);
uint32 noScripts = (int32)READ_LE_UINT32(code); uint32 noScripts = (int32) READ_LE_UINT32(code);
if ( (*offset) < noScripts)
{ ip = (int32)READ_LE_UINT32((const int *)code + (*offset) + 1); if (*offset < noScripts) {
DEBUG2("Start script %d with offset %d",*offset,ip); ip = READ_LE_UINT32((const int *) code + *offset + 1);
} DEBUG("Start script %d with offset %d",*offset,ip);
else } else {
{ ip = (*offset); ip = *offset;
DEBUG1("Start script with offset %d",ip); DEBUG("Start script with offset %d",ip);
} }
code += noScripts * sizeof(int) + sizeof(int); code += noScripts * sizeof(int) + sizeof(int);
/************************************************************************************************/
#ifdef DONTPROCESSSCRIPTCHECKSUM #ifdef DONTPROCESSSCRIPTCHECKSUM
code += sizeof(int) * 3;
#else
// Code should nop be pointing at an identifier and a checksum
const int *checksumBlock = (const int *) code;
code += sizeof(int) * 3; code += sizeof(int) * 3;
#else if (READ_LE_UINT32(checksumBlock) != 12345678) {
Con_fatal_error("Invalid script in object %s", header->name);
// Code should nopw be pointing at an identifier and a checksum return 0;
const int *checksumBlock = (const int *)code;
code += sizeof(int) * 3;
if ((int32)READ_LE_UINT32(checksumBlock) != 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 = (int32)READ_LE_UINT32(checksumBlock + 1);
int codeLen = READ_LE_UINT32(checksumBlock + 1);
int checksum = 0; int checksum = 0;
for (int count = 0 ; count < codeLen ; count++)
checksum += (unsigned char)code[count]; for (count = 0; count < codeLen; count++)
if ( checksum != (int32)READ_LE_UINT32(checksumBlock + 2) ) checksum += (unsigned char) code[count];
{
#ifdef INSIDE_LINC if (checksum != (int32) READ_LE_UINT32(checksumBlock + 2)) {
AfxMessageBox(CVString("Checksum error in script %s",header->name)); Con_fatal_error("Checksum error in object %s", header->name);
#else return 0;
Con_fatal_error("Checksum error in object %s",header->name);
#endif
return(0);
} }
#endif
#endif //DONTPROCESSSCRIPTCHECKSUM
/************************************************************************************************/
int runningScript = 1; int runningScript = 1;
while ( runningScript )
{ curCommand = code[ip++]; while (runningScript) {
switch(curCommand) curCommand = code[ip++];
{ case CP_END_SCRIPT: // 0 End the script
DEBUG1("End script",0); switch(curCommand) {
case CP_END_SCRIPT:
// End the script
DEBUG("End script",0);
runningScript = 0; runningScript = 0;
#ifdef INSIDE_LINC
engine.AddTextLine( "End script" , VS_COL_GREY );
engine.AddTextLine( "" , VS_COL_GREY );
#endif
break; break;
case CP_PUSH_LOCAL_VAR32: // 1 Push the contents of a local variable case CP_PUSH_LOCAL_VAR32:
Read16ip(parameter) // Push the contents of a local variable
DEBUG2("Push local var %d (%d)",parameter,*(int32 *)(variables+parameter)); Read16ip(parameter);
PUSHONSTACK ( *(int32 *)(variables+parameter) ); DEBUG("Push local var %d (%d)", parameter, *(int32 *) (variables + parameter));
PUSHONSTACK(*(int32 *) (variables + parameter));
break; break;
case CP_PUSH_GLOBAL_VAR32:
case CP_PUSH_GLOBAL_VAR32: // 2 Push a global variable // Push a global variable
Read16ip(parameter) Read16ip(parameter);
#ifdef INSIDE_LINC DEBUG("Push global var %d (%d)", parameter, globalInterpreterVariables2[parameter]);
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); ASSERT(globalInterpreterVariables2);
PUSHONSTACK ( globalInterpreterVariables2[parameter] ); PUSHONSTACK(globalInterpreterVariables2[parameter]);
#endif
break; break;
case CP_POP_LOCAL_VAR32: // 3 Pop a value into a local word variable case CP_POP_LOCAL_VAR32:
Read16ip(parameter) // Pop a value into a local word variable
POPOFFSTACK ( value ); Read16ip(parameter);
DEBUG2("Pop %d into var %d",value,parameter); POPOFFSTACK(value);
*((int32 *)(variables+parameter)) = value; DEBUG("Pop %d into var %d", value, parameter);
*((int32 *) (variables + parameter)) = value;
break; break;
case CP_CALL_MCODE: // 4 Call an mcode routine case CP_CALL_MCODE:
{ // Call an mcode routine
Read16ip(parameter) Read16ip(parameter);
ASSERT(parameter <= MAX_FN_NUMBER); ASSERT(parameter <= MAX_FN_NUMBER);
value = *((const int8 *)(code+ip)); // amount to adjust stack by (no of parameters) // amount to adjust stack by (no of parameters)
ip ++; Read8ip(value);
DEBUG2("Call mcode %d with stack = %x",parameter,stack2+(stackPointer2-value)); DEBUG("Call mcode %d with stack = %x", parameter, stack2 + stackPointer2 - value);
#ifdef INSIDE_LINC retVal = McodeTable[parameter](stack2 + stackPointer2 - value);
int retVal = engine.McodeTable(parameter , stack2+(stackPointer2-value));
#else
int retVal = McodeTable[parameter](stack2+(stackPointer2-value));
#endif
stackPointer2 -= value; stackPointer2 -= value;
CHECKSTACKPOINTER2 CHECKSTACKPOINTER2
switch ( retVal & 7 )
{ case IR_STOP: // 0: Quit out for a cycle
*offset = ip;
return(0);
case IR_CONT: // 1: // Continue as normal switch (retVal & 7) {
case IR_STOP:
// Quit out for a cycle
*offset = ip;
return 0;
case IR_CONT:
// Continue as normal
break; break;
case IR_TERMINATE: // 2: case IR_TERMINATE:
// Return without updating the offset // Return without updating the
return(2); // offset
return 2;
case IR_REPEAT: // 3: case IR_REPEAT:
// Return setting offset to start of this function call // Return setting offset to
// start of this function call
*offset = savedStartOfMcode; *offset = savedStartOfMcode;
return(0); return 0;
case IR_GOSUB: // 4: //that's really neat case IR_GOSUB:
// that's really neat
*offset = ip; *offset = ip;
return(2); return 2;
default: default:
ASSERT(FALSE); ASSERT(FALSE);
} }
parameterReturnedFromMcodeFunction = retVal >> 3; parameterReturnedFromMcodeFunction = retVal >> 3;
}
break; break;
case CP_PUSH_LOCAL_ADDR: // 5 push the address of a local variable case CP_PUSH_LOCAL_ADDR:
Read16ip(parameter) // push the address of a local variable
DEBUG2("Push address of local variable %d (%x)",parameter,(int32)(variables + parameter)); Read16ip(parameter);
PUSHONSTACK ( (int32)(variables + parameter) ); DEBUG("Push address of local variable %d (%x)", parameter, (int32) (variables + parameter));
PUSHONSTACK((int32) (variables + parameter));
break; break;
case CP_PUSH_INT32: // 6 Push a long word value on to the stack case CP_PUSH_INT32:
Read32ip(parameter) // Push a long word value on to the stack
DEBUG2("Push int32 %d (%x)",parameter,parameter); Read32ip(parameter);
PUSHONSTACK ( parameter ); DEBUG("Push int32 %d (%x)", parameter, parameter);
PUSHONSTACK(parameter);
break; break;
case CP_SKIPONFALSE:
case CP_SKIPONFALSE: // 7 Skip if the value on the stack is false // Skip if the value on the stack is false
Read32ipLeaveip(parameter) Read32ipLeaveip(parameter);
POPOFFSTACK ( value ); POPOFFSTACK(value);
DEBUG2("Skip %d if %d is false",parameter,value); DEBUG("Skip %d if %d is false", parameter, value);
if (value) if (value)
ip += sizeof(int32); ip += sizeof(int32);
else else
ip += parameter; ip += parameter;
break; break;
case CP_SKIPALLWAYS: // 8 skip a block case CP_SKIPALWAYS:
Read32ipLeaveip(parameter) // skip a block
DEBUG1("Skip %d",parameter); Read32ipLeaveip(parameter);
DEBUG("Skip %d", parameter);
ip += parameter; ip += parameter;
break; break;
case CP_SWITCH: // 9 switch case CP_SWITCH:
{ POPOFFSTACK ( value ); // 9 switch
int caseCount; POPOFFSTACK(value);
Read32ip(caseCount) Read32ip(caseCount);
// Search the cases // Search the cases
int foundCase = 0; foundCase = 0;
for (int count = 0 ; (count < caseCount) && (!foundCase) ; count++) for (count = 0; count < caseCount && !foundCase; count++) {
{ if (value == (int32) READ_LE_UINT32(code + ip)) {
if (value == (int32)READ_LE_UINT32(code+ip)) // We have found the case, so
{ // We have found the case, so lets jump to it // lets jump to it
foundCase = 1; foundCase = 1;
ip += (int32)READ_LE_UINT32(code+ip+sizeof(int32)); ip += READ_LE_UINT32(code + ip + sizeof(int32));
} } else
else
ip += sizeof(int32) * 2; ip += sizeof(int32) * 2;
} }
// If we found no matching case then use the default
// If we found no matching case then use the
// default
if (!foundCase) if (!foundCase)
{ ip += READ_LE_UINT32(code + ip);
ip += (int32)READ_LE_UINT32(code+ip);
}
}
break; break;
case CP_ADDNPOP_LOCAL_VAR32: // 10 case CP_ADDNPOP_LOCAL_VAR32:
Read16ip(parameter) Read16ip(parameter);
POPOFFSTACK ( value ); POPOFFSTACK(value);
*((int32 *)(variables+parameter)) += value; *((int32 *) (variables + parameter)) += value;
DEBUG3("+= %d into var %d->%d",value,parameter,*(int32 *)(variables+parameter)); DEBUG("+= %d into var %d->%d", value, parameter, *(int32 *) (variables + parameter));
break; break;
case CP_SUBNPOP_LOCAL_VAR32: // 11 case CP_SUBNPOP_LOCAL_VAR32:
Read16ip(parameter) Read16ip(parameter);
POPOFFSTACK ( value ); POPOFFSTACK(value);
*((int32 *)(variables+parameter)) -= value; *((int32 *) (variables + parameter)) -= value;
DEBUG3("-= %d into var %d->%d",value,parameter,*(int32 *)(variables+parameter)); DEBUG("-= %d into var %d->%d", value, parameter, *(int32 *) (variables + parameter));
break; break;
case CP_SKIPONTRUE: // 12 Skip if the value on the stack is TRUE case CP_SKIPONTRUE:
Read32ipLeaveip(parameter) // Skip if the value on the stack is TRUE
POPOFFSTACK ( value ); Read32ipLeaveip(parameter);
DEBUG2("Skip %d if %d is false",parameter,value); POPOFFSTACK(value);
DEBUG("Skip %d if %d is false", parameter, value);
if (!value) if (!value)
ip += sizeof(int32); ip += sizeof(int32);
else else
ip += parameter; ip += parameter;
break; break;
case CP_POP_GLOBAL_VAR32: // 13 // Pop a global variable case CP_POP_GLOBAL_VAR32:
Read16ip(parameter) // Pop a global variable
POPOFFSTACK ( value ); Read16ip(parameter);
DEBUG2("Pop %d into global var %d",value,parameter); POPOFFSTACK(value);
#ifdef INSIDE_LINC DEBUG("Pop %d into global var %d", value, parameter);
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 #ifdef TRACEGLOBALVARIABLESET
TRACEGLOBALVARIABLESET(parameter,value); TRACEGLOBALVARIABLESET(parameter, value);
#endif #endif
globalInterpreterVariables2[parameter] = value; globalInterpreterVariables2[parameter] = value;
#endif
break; break;
case CP_ADDNPOP_GLOBAL_VAR32: // 14 Add and pop a global variable case CP_ADDNPOP_GLOBAL_VAR32:
{ Read16ip(parameter) // Add and pop a global variable
// parameter = *((int16_TYPE *)(code+ip)); Read16ip(parameter);
// ip += 2; // parameter = *((int16_TYPE *) (code + ip));
POPOFFSTACK ( value ); // ip += 2;
#ifdef INSIDE_LINC POPOFFSTACK(value);
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; globalInterpreterVariables2[parameter] += value;
DEBUG3("+= %d into global var %d->%d",value,parameter,*(int32 *)(variables+parameter)); DEBUG("+= %d into global var %d->%d", value, parameter, *(int32 *) (variables + parameter));
#endif
break; break;
}
case CP_SUBNPOP_GLOBAL_VAR32: // 15 Sub and pop a global variable case CP_SUBNPOP_GLOBAL_VAR32:
{ Read16ip(parameter) // Sub and pop a global variable
// parameter = *((int16_TYPE *)(code+ip)); Read16ip(parameter);
// ip += 2; POPOFFSTACK(value);
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; globalInterpreterVariables2[parameter] -= value;
DEBUG3("-= %d into global var %d->%d",value,parameter,*(int32 *)(variables+parameter)); DEBUG("-= %d into global var %d->%d", value, parameter, *(int32 *) (variables + parameter));
#endif
break; break;
}
case CP_DEBUGON: case CP_DEBUGON:
// Turn debugging on // Turn debugging on
@ -609,187 +562,195 @@ int RunScript ( char * scriptData , char * objectData , uint32 *offset )
break; break;
case CP_QUIT: case CP_QUIT:
#ifdef INSIDE_LINC
break;
#else
// Quit out for a cycle // Quit out for a cycle
*offset = ip; *offset = ip;
return(0); return 0;
#endif
case CP_TERMINATE: case CP_TERMINATE:
// Quit out immediately without affecting the offset pointer // Quit out immediately without affecting the
return(3); // offset pointer
return 3;
/******************************************************************************************************************
******************************************************************************************************************/
// Operators // Operators
case OP_ISEQUAL: // 20 // '==' case OP_ISEQUAL:
DEBUG3("%d == %d -> %d", stack2[stackPointer2-2], // '=='
stack2[stackPointer2-1], DEBUG("%d == %d -> %d",
stack2[stackPointer2-2] == stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] == stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] == stack2[stackPointer2 - 1]);
DOOPERATION (stack2[stackPointer2 - 2] == stack2[stackPointer2 - 1]);
break; break;
case OP_PLUS: // 21 // '+' case OP_PLUS:
DEBUG3("%d + %d -> %d", stack2[stackPointer2-2], // '+'
stack2[stackPointer2-1], DEBUG("%d + %d -> %d",
stack2[stackPointer2-2] + stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] + stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] + stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] + stack2[stackPointer2 - 1]);
break; break;
case OP_MINUS: // 22 // '+' case OP_MINUS:
DEBUG3("%d - %d -> %d", stack2[stackPointer2-2], // '-'
stack2[stackPointer2-1], DEBUG("%d - %d -> %d",
stack2[stackPointer2-2] - stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] - stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] - stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] - stack2[stackPointer2 - 1]);
break; break;
case OP_TIMES: // 23 // '+' case OP_TIMES:
DEBUG3("%d * %d -> %d", stack2[stackPointer2-2], // '*'
stack2[stackPointer2-1], DEBUG("%d * %d -> %d",
stack2[stackPointer2-2] * stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] * stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] * stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] * stack2[stackPointer2 - 1]);
break; break;
case OP_DEVIDE: // 24 // '+' case OP_DIVIDE:
DEBUG3("%d / %d -> %d", stack2[stackPointer2-2], // '/'
stack2[stackPointer2-1], DEBUG("%d / %d -> %d",
stack2[stackPointer2-2] / stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] / stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] / stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] / stack2[stackPointer2 - 1]);
break; break;
case OP_NOTEQUAL: // 25 // '!=' case OP_NOTEQUAL:
DEBUG3("%d != %d -> %d", stack2[stackPointer2-2], // '!='
stack2[stackPointer2-1], DEBUG("%d != %d -> %d",
stack2[stackPointer2-2] != stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] != stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] != stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] != stack2[stackPointer2 - 1]);
break; break;
case OP_ANDAND: // 26 case OP_ANDAND:
DEBUG3("%d != %d -> %d", stack2[stackPointer2-2], // '&&'
stack2[stackPointer2-1], DEBUG("%d != %d -> %d",
stack2[stackPointer2-2] && stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] && stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] && stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] && stack2[stackPointer2 - 1]);
break; break;
case OP_GTTHAN: // 27 > case OP_GTTHAN:
DEBUG3("%d > %d -> %d", stack2[stackPointer2-2], // '>'
stack2[stackPointer2-1], DEBUG("%d > %d -> %d",
stack2[stackPointer2-2] > stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] > stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] > stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] > stack2[stackPointer2 - 1]);
break; break;
case OP_LSTHAN: // 28 < case OP_LSTHAN:
DEBUG3("%d < %d -> %d", stack2[stackPointer2-2], // '<'
stack2[stackPointer2-1], DEBUG("%d < %d -> %d",
stack2[stackPointer2-2] < stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] < stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] < stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] < stack2[stackPointer2 - 1]);
break; break;
case CP_JUMP_ON_RETURNED: // 29 case CP_JUMP_ON_RETURNED:
{ // Jump to a part of the script depending on the return value from an mcode routine // Jump to a part of the script depending on
parameter = *((const int8 *)(code+ip)); // Get the maximum value // the return value from an mcode routine
ip++;
#ifdef INSIDE_LINC
TRACE("ip %d: Parameter %d skip %d\r\n", ip,
parameterReturnedFromMcodeFunction,
(int32)READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4) );
#endif
ip += (int32)READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4); // Get the maximum value
} Read8ip(parameter);
ip += READ_LE_UINT32(code + ip + parameterReturnedFromMcodeFunction * 4);
break; break;
case CP_TEMP_TEXT_PROCESS: // 30 case CP_TEMP_TEXT_PROCESS:
// Process a text line // Process a text line
Read32ip(parameter) // This was apparently used in Linc
// parameter = *((int32_TYPE *)(code+ip)); Read32ip(parameter);
// ip += sizeof(int32_TYPE);; DEBUG("Process text id %d", parameter);
DEBUG1("Process text id %d",parameter);
#ifdef INSIDE_LINC
// Linc only for the moment
engine.ProcessTextLine(parameter);
#endif //INSIDE_LINC
break; break;
case CP_SAVE_MCODE_START: // 31 case CP_SAVE_MCODE_START:
// Save the start position on an mcode instruction in case we need to restart it again // Save the start position on an mcode
savedStartOfMcode = ip-1; // instruction in case we need to restart it
// again
savedStartOfMcode = ip - 1;
break; break;
case CP_RESTART_SCRIPT: // 32 case CP_RESTART_SCRIPT:
{ // Start the script again // Start the script again
// Do a ip search to find the script we are running // Do a ip search to find the script we are
const char *tempScrPtr = scriptData + (int32)READ_LE_UINT32(scriptData) + sizeof(int); // running
int scriptNumber = 0;
int foundScript = 0; tempScrPtr = scriptData + READ_LE_UINT32(scriptData) + sizeof(int);
uint32 count = 0; scriptNumber = 0;
for (count = 1 ; (count < noScripts) && (!foundScript) ; count++) foundScript = 0;
{ if (ip < ((const int *)tempScrPtr)[count+1])
{ scriptNumber = count - 1 ; for (count = 1; count < (int) noScripts && !foundScript; count++) {
if (ip < ((const int *) tempScrPtr)[count + 1]) {
scriptNumber = count - 1;
foundScript = 1; foundScript = 1;
} }
} }
if (!foundScript) if (!foundScript)
scriptNumber = count - 1 ; scriptNumber = count - 1;
// So we know what script we are running, lets restart it
ip = ((const int *)tempScrPtr)[scriptNumber+1];
break;
}
case CP_PUSH_STRING: // 33 // So we know what script we are running,
{ // Push the address of a string on to the stack // lets restart it
parameter = *((const int8 *)(code+ip)); // Get the string size
ip += 1; ip = ((const int *) tempScrPtr)[scriptNumber + 1];
break;
case CP_PUSH_STRING:
// Push the address of a string on to the stack
// Get the string size
Read8ip(parameter);
// ip points to the string // ip points to the string
PUSHONSTACK( (int)(code+ip) ); PUSHONSTACK((int) (code + ip));
ip += (parameter+1); 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; break;
case OP_LSTHANE: // 36 <= case CP_PUSH_DEREFERENCED_STRUCTURE:
DEBUG3("%d < %d -> %d", stack2[stackPointer2-2], // Push the address of a dereferenced structure
stack2[stackPointer2-1], Read32ip(parameter);
stack2[stackPointer2-2] <= stack2[stackPointer2-1]); DEBUG("Push address of far variable (%x)", (int32) (variables + parameter));
DOOPERATION ( (stack2[stackPointer2-2] <= stack2[stackPointer2-1]) ); PUSHONSTACK((int) (objectData + sizeof(int) + sizeof(_standardHeader) + sizeof(_object_hub) + parameter));
break; break;
case OP_OROR: // 37 case OP_GTTHANE:
DEBUG3("%d || %d -> %d", stack2[stackPointer2-2], // '>='
stack2[stackPointer2-1], DEBUG("%d > %d -> %d",
stack2[stackPointer2-2] || stack2[stackPointer2-1]); stack2[stackPointer2 - 2],
DOOPERATION ( (stack2[stackPointer2-2] || stack2[stackPointer2-1]) ); stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] >= stack2[stackPointer2 - 1]);
DOOPERATION(stack2[stackPointer2 - 2] >= stack2[stackPointer2 - 1]);
break; break;
case OP_LSTHANE:
// '<='
DEBUG("%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:
// '||'
DEBUG("%d || %d -> %d",
stack2[stackPointer2 - 2],
stack2[stackPointer2 - 1],
stack2[stackPointer2 - 2] || stack2[stackPointer2 - 1]);
DOOPERATION (stack2[stackPointer2 - 2] || stack2[stackPointer2 - 1]);
break;
default: default:
#ifdef INSIDE_LINC
AfxMessageBox(CVString("Invalid interpreter token %d",curCommand));
#else
Con_fatal_error("Interpreter error: Invalid token %d", curCommand); Con_fatal_error("Interpreter error: Invalid token %d", curCommand);
#endif return 3;
return(3);
} }
} }
return(1); return 1;
} }

View file

@ -17,157 +17,81 @@
* $Header$ * $Header$
*/ */
// Interpreter return codes #ifndef _INTERPRETER
#define _INTERPRETER
#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 _SWORD2_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 //_SWORD2_DEBUG
#define DEBUG1
#define DEBUG2
#define DEBUG3
#endif //_SWORD2_DEBUG
#else //INSIDE_LINC
//#include "src\driver96.h"
#include "debug.h" #include "debug.h"
#include "header.h" #include "header.h"
#define DEBUG1 if(g_debugFlag)Zdebug // Interpreter return codes
#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");}} #define IR_STOP 0
#define IR_CONT 1
#define IR_TERMINATE 2
#define IR_REPEAT 3
#define IR_GOSUB 4
#define DEBUG if (g_debugFlag) Zdebug
#endif #define ASSERT(x) { if (!(x)) { Zdebug("Interpreter ASSERT %s,%d", __FILE__, __LINE__); Con_fatal_error("Assert error in interpreter"); } }
// Get parameter fix so that the playstation version can handle words not on
// word boundaries
// Get parameter fix so that the playstation version can handle words not on word boundaries #define Read8ip(var) { var = *((const int8 *) (code + ip)); ip++; }
#define Read16ip(var) {var = (int16)READ_LE_UINT16(code+ip);ip+=sizeof(int16);} #define Read16ip(var) { var = (int16) READ_LE_UINT16(code + ip); ip += sizeof(int16); }
#define Read32ip(var) {var = (int32)READ_LE_UINT32(code+ip);ip+=sizeof(int32);} #define Read32ip(var) { var = (int32) READ_LE_UINT32(code + ip); ip += sizeof(int32); }
#define Read32ipLeaveip(var) {var = (int32)READ_LE_UINT32(code+ip);} #define Read32ipLeaveip(var) { var = (int32) READ_LE_UINT32(code + ip); }
void SetGlobalInterpreterVariables(int32 *vars); void SetGlobalInterpreterVariables(int32 *vars);
int RunScript (char *scriptData, char *objectData, uint32 *offset);
// 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_SKIPALWAYS 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_DIVIDE 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
#ifdef INSIDE_LINC // Are we running in linc?
int RunScript ( MCBOVirtualSword &engine , const char * scriptData , char * /*objectData*/ , uint32 *offset );
#else
int RunScript ( char * scriptData , char * /*objectData*/ , uint32 *offset );
#endif #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

View file

@ -23,102 +23,103 @@
#include "driver/driver96.h" #include "driver/driver96.h"
// these structures represent the broken up compact components // 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) // 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 and bottom-right of mouse
int32 y1; // area. (These coords are inclusive.)
int32 x2;
int32 y2;
int32 priority;
int32 pointer; // type (or resource id?) of pointer used over this area
// 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; } Object_mouse;
// logic structure - contains fields used in logic script processing // logic structure - contains fields used in logic script processing
typedef struct
{ typedef struct {
int32 looping; // 0 when first calling FN_<function>; 1 when calling subsequent times in same loop int32 looping; // 0 when first calling FN_<function>;
int32 pause; // pause count, used by FN_pause() // 1 when calling subsequent times in same loop
int32 pause; // pause count, used by FN_pause()
} Object_logic; } Object_logic;
//------------------------------------------------
// status bits for 'type' field of Object_graphic) // status bits for 'type' field of Object_graphic)
// in low word: // in low word:
#define NO_SPRITE 0x00000000 // don't print
#define BGP0_SPRITE 0x00000001 // fixed to background parallax[0] #define NO_SPRITE 0x00000000 // don't print
#define BGP1_SPRITE 0x00000002 // fixed to background parallax[1] #define BGP0_SPRITE 0x00000001 // fixed to background parallax[0]
#define BACK_SPRITE 0x00000004 // 'background' sprite, fixed to main background #define BGP1_SPRITE 0x00000002 // fixed to background parallax[1]
#define SORT_SPRITE 0x00000008 // 'sorted' sprite, fixed to main background #define BACK_SPRITE 0x00000004 // 'background' sprite, fixed to main background
#define FORE_SPRITE 0x00000010 // 'foreground' sprite, fixed to main background #define SORT_SPRITE 0x00000008 // 'sorted' sprite, fixed to main background
#define FGP0_SPRITE 0x00000020 // fixed to foreground parallax[0] #define FORE_SPRITE 0x00000010 // 'foreground' sprite, fixed to main background
#define FGP1_SPRITE 0x00000040 // fixed to foreground parallax[0] #define FGP0_SPRITE 0x00000020 // fixed to foreground parallax[0]
#define FGP1_SPRITE 0x00000040 // fixed to foreground parallax[0]
// in high word: // in high word:
#define UNSHADED_SPRITE 0x00000000 // not to be shaded #define UNSHADED_SPRITE 0x00000000 // not to be shaded
#define SHADED_SPRITE 0x00010000 // to be shaded, based on shading mask #define SHADED_SPRITE 0x00010000 // to be shaded, based on shading mask
//------------------------------------------------
// graphic structure - contains fields appropriate to sprite output // graphic structure - contains fields appropriate to sprite output
typedef struct
{ typedef struct {
int32 type; // see above int32 type; // see above
int32 anim_resource; // resource id of animation file int32 anim_resource; // resource id of animation file
int32 anim_pc; // current frame number of animation int32 anim_pc; // current frame number of animation
} Object_graphic; } Object_graphic;
// speech structure - contains fields used by speech scripts & text output // speech structure - contains fields used by speech scripts & text output
typedef struct
{ typedef struct {
int32 pen; // colour to use for body of characters int32 pen; // colour to use for body of characters
int32 width; // max width of text sprite int32 width; // max width of text sprite
int32 command; // speech script command id int32 command; // speech script command id
int32 ins1; // speech script instruction parameters (may need more now?) int32 ins1; // speech script instruction parameters (may need more now?)
int32 ins2; int32 ins2;
int32 ins3; int32 ins3;
int32 ins4; int32 ins4;
int32 ins5; int32 ins5;
int32 wait_state; //0 not waiting 1 waiting for next speech command int32 wait_state; // 0 not waiting, 1 waiting for next speech command
} Object_speech; } Object_speech;
// mega structure - contains fields used for mega-character & mega-set
// processing
// mega structure - contains fields used for mega-character & mega-set processing typedef struct {
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_1; // only free roaming megas need to check this before registering their graphics for drawing int32 NOT_USED_3; // id of object which we are getting to
int32 NOT_USED_2; // id of floor on which we are standing int32 NOT_USED_4; // pixel distance to stand from player character when in conversation
int32 NOT_USED_3; // id of object which we are getting to int32 currently_walking; // number given us by the auto router
int32 NOT_USED_4; // pixel distance to stand from player character when in conversation int32 walk_pc; // current frame number of walk-anim
int32 currently_walking; // number given us by the auto router int32 scale_a; // current scale factors, taken from floor data
int32 walk_pc; // current frame number of walk-anim int32 scale_b;
int32 scale_a; // current scale factors, taken from floor data int32 feet_x; // mega feet coords - frame-offsets are added to these position mega frames
int32 scale_b; int32 feet_y;
int32 feet_x; // mega feet coords - frame-offsets are added to these position mega frames int32 current_dir; // current dirction faced by mega; used by autorouter to determine turns required
int32 feet_y; int32 NOT_USED_5; // means were currently avoiding a collision (see FN_walk)
int32 current_dir; // current dirction faced by mega; used by autorouter to determine turns required int32 megaset_res; // resource id of mega-set file
int32 colliding; // means were currently avoiding a collision (see FN_walk) int32 NOT_USED_6; // NOT USED
int32 megaset_res; // resource id of mega-set file
int32 NOT_USED_5; // NOT USED
} Object_mega; } Object_mega;
// walk-data structure - contains details of layout of frames in the
// mega-set, and how they are to be used
// walk-data structure - contains details of layout of frames in the mega-set, and how they are to be used typedef struct {
typedef struct int32 nWalkFrames; // no. of frames per walk-cycle
{ int32 usingStandingTurnFrames; // 0 = no 1 = yes
int32 nWalkFrames; // no. of frames per walk-cycle int32 usingWalkingTurnFrames; // 0 = no 1 = yes
int32 usingStandingTurnFrames; // 0=no 1=yes int32 usingSlowInFrames; // 0 = no 1 = yes
int32 usingWalkingTurnFrames; // 0=no 1=yes int32 usingSlowOutFrames; // 0 = no !0 = number of slow-out frames in each direction
int32 usingSlowInFrames; // 0=no 1=yes int32 nSlowInFrames[8]; // no. of slow-in frames in each direction
int32 usingSlowOutFrames; // 0=no !0=number of slow-out frames in each direction int32 leadingLeg[8]; // leading leg for walk in each direction (0 = left 1 = right)
int32 nSlowInFrames[8]; // no. of slow-in frames in each direction int32 dx[8 * (12 + 1)]; // walk step distances in x direction
int32 leadingLeg[8]; // leading leg for walk in each direction (0=left 1=right) int32 dy[8 * (12 + 1)]; // walk step distances in y direction
int32 dx[8*(12+1)]; // walk step distances in x direction
int32 dy[8*(12+1)]; // walk step distances in y direction
} Object_walkdata; } Object_walkdata;
#endif #endif

View file

@ -17,139 +17,159 @@
* $Header$ * $Header$
*/ */
//------------------------------------------------------------------------------------
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "stdafx.h" #include "stdafx.h"
//#include "src\driver96.h"
#include "build_display.h"
#include "debug.h" #include "debug.h"
#include "defs.h" #include "defs.h"
#include "header.h" #include "header.h"
#include "interpreter.h" #include "interpreter.h"
#include "layers.h" #include "layers.h"
#include "memory.h"
#include "object.h"
#include "protocol.h"
#include "resman.h"
#include "scroll.h" #include "scroll.h"
//------------------------------------------------------------------------------------ // max no of pixel allowed to scroll per cycle
#define MAX_SCROLL_DISTANCE 8 // max no of pixel allowed to scroll per cycle #define MAX_SCROLL_DISTANCE 8
//------------------------------------------------------------------------------------ // used to be a define, but now it's flexible (see new functions below)
uint8 scroll_fraction=16; // used to be a define, but now it's flexible (see new functions below) uint8 scroll_fraction = 16;
//------------------------------------------------------------------------------------
void Set_scrolling(void) //S2.1(2Mar94jel) refurnished Tony25Sept96 :-) void Set_scrolling(void) { // S2.1(2Mar94jel) refurnished Tony25Sept96 :-)
{ // normally we aim to get George's feet at (320,250) from top left
// feet_x = 128+320 // normally we aim to get George's feet at (320,250) from top left of screen window // of screen window
// feet_y = 128+250 // feet_x = 128 + 320
// feet_y = 128 + 250
// set scroll offsets according to the player's coords // set scroll offsets according to the player's coords
int16 offset_x; int16 offset_x;
int16 offset_y; int16 offset_y;
int16 dx, dy; int16 dx, dy;
uint16 scroll_distance_x; // how much we want to scroll uint16 scroll_distance_x; // how much we want to scroll
uint16 scroll_distance_y; uint16 scroll_distance_y;
// if the scroll offsets are being forced in script (05feb97 JAMES)
if (SCROLL_X || SCROLL_Y) // if the scroll offsets are being forced in script (05feb97 JAMES) if (SCROLL_X || SCROLL_Y) {
{
// ensure not too far right // ensure not too far right
if (SCROLL_X < this_screen.max_scroll_offset_x) if (this_screen.max_scroll_offset_x > SCROLL_X)
this_screen.scroll_offset_x = SCROLL_X; this_screen.scroll_offset_x = SCROLL_X;
else else
this_screen.scroll_offset_x = this_screen.max_scroll_offset_x; this_screen.scroll_offset_x = this_screen.max_scroll_offset_x;
// ensure not too far down // ensure not too far down
if (SCROLL_Y < this_screen.max_scroll_offset_y) if (this_screen.max_scroll_offset_y > SCROLL_Y)
this_screen.scroll_offset_y = SCROLL_Y; this_screen.scroll_offset_y = SCROLL_Y;
else else
this_screen.scroll_offset_y = this_screen.max_scroll_offset_y; this_screen.scroll_offset_y = this_screen.max_scroll_offset_y;
} } else {
else // George's offset from the centre - the desired position
{ // for him
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;
offset_x = this_screen.player_feet_x - this_screen.feet_x;
offset_y = this_screen.player_feet_y - this_screen.feet_y;
// prevent scrolling too far left/right/up/down // 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! if (offset_x < 0)
{ offset_x = 0;
//Zdebug(42,"init scroll"); else if ((uint32) offset_x > this_screen.max_scroll_offset_x)
offset_x = this_screen.max_scroll_offset_x;
if (offset_y < 0)
offset_y = 0;
else if ((uint32) offset_y > this_screen.max_scroll_offset_y)
offset_y = this_screen.max_scroll_offset_y;
// first time on this screen - need absolute scroll
// immediately!
if (this_screen.scroll_flag == 2) {
// Zdebug(42,"init scroll");
this_screen.scroll_offset_x = offset_x; this_screen.scroll_offset_x = offset_x;
this_screen.scroll_offset_y = offset_y; this_screen.scroll_offset_y = offset_y;
this_screen.scroll_flag=1; this_screen.scroll_flag = 1;
} } else {
else // catch up with required scroll offsets - speed depending on distance to catch up (dx and dy) & 'SCROLL_FRACTION' used // catch up with required scroll offsets - speed
{ // but limit to certain number of pixels per cycle (MAX_SCROLL_DISTANCE) // 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; dx = this_screen.scroll_offset_x - offset_x;
dy = this_screen.scroll_offset_y - offset_y; dy = this_screen.scroll_offset_y - offset_y;
if (dx < 0) // current scroll_offset_x is less than the required value // 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; // 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 (dx < 0) {
// => inc by (fraction of the differnce)
// NB. dx is -ve, so we subtract
// dx / SCROLL_FRACTION
scroll_distance_x = 1 - dx / scroll_fraction;
if (scroll_distance_x > MAX_SCROLL_DISTANCE)
scroll_distance_x = MAX_SCROLL_DISTANCE;
this_screen.scroll_offset_x += scroll_distance_x; } else if (dx > 0) {
// current scroll_offset_x is greater than
// the required value
// => dec by (fraction of the differnce)
scroll_distance_x = 1 + dx / scroll_fraction;
if (scroll_distance_x > MAX_SCROLL_DISTANCE)
scroll_distance_x = MAX_SCROLL_DISTANCE;
this_screen.scroll_offset_x -= scroll_distance_x;
} }
else if (dx > 0) // current scroll_offset_x is greater than the required value
{ if (dy < 0) {
scroll_distance_x = (1+dx/scroll_fraction); // => dec by (fraction of the differnce) scroll_distance_y = 1 - dy / scroll_fraction;
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 if (scroll_distance_y > MAX_SCROLL_DISTANCE)
// not scroll at all when dx < SCROLL_FRACTION scroll_distance_y = MAX_SCROLL_DISTANCE;
if (dy < 0)
{ this_screen.scroll_offset_y += scroll_distance_y;
scroll_distance_y = (1+(-dy)/scroll_fraction); } else if (dy > 0) {
this_screen.scroll_offset_y += scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE; scroll_distance_y = 1 + dy / scroll_fraction;
}
else if (dy > 0) if (scroll_distance_y > MAX_SCROLL_DISTANCE)
{ scroll_distance_y = MAX_SCROLL_DISTANCE;
scroll_distance_y = (1+dy/scroll_fraction);
this_screen.scroll_offset_y -= scroll_distance_y < MAX_SCROLL_DISTANCE ? scroll_distance_y : MAX_SCROLL_DISTANCE; this_screen.scroll_offset_y -= scroll_distance_y;
} }
} }
} }
} }
//------------------------------------------------------------------------------------
int32 FN_set_scroll_coordinate(int32 *params) //Tony25Sept96 int32 FN_set_scroll_coordinate(int32 *params) { // Tony25Sept96
{
// set the special scroll offset variables // set the special scroll offset variables
// call when starting screens and to change the camera within screens // call when starting screens and to change the camera within screens
// call AFTER FN_init_background() to override the defaults // 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 // called feet_x and feet_y to retain intelectual compatibility with
// param 1 feet_y value // Sword1 !
// feet_x & feet_y refer to the physical screen coords where the
// system will try to maintain George's feet
// params: 0 feet_x value
// 1 feet_y value
this_screen.feet_x = params[0]; this_screen.feet_x = params[0];
this_screen.feet_y = params[1]; this_screen.feet_y = params[1];
return IR_CONT;
return(IR_CONT);
} }
//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------
int32 FN_set_scroll_speed_normal(int32 *params) // James08aug97
{
scroll_fraction=16;
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); int32 FN_set_scroll_speed_slow(int32 *params) { // James08aug97
scroll_fraction = 32;
return IR_CONT;
} }
//------------------------------------------------------------------------------------

View file

@ -17,13 +17,11 @@
* $Header$ * $Header$
*/ */
//the usual suspects // the usual suspects
#ifndef _SCROLL #ifndef _SCROLL
#define _SCROLL #define _SCROLL
//#include "src\driver96.h" void Set_scrolling(void);
void Set_scrolling(void);
#endif #endif

View file

@ -17,346 +17,330 @@
* $Header$ * $Header$
*/ */
//-------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// BROKEN SWORD 2 // BROKEN SWORD 2
// //
// SOUND.CPP Contains the sound engine, fx & music functions // SOUND.CPP Contains the sound engine, fx & music functions
// Some very 'sound' code in here ;) // Some very 'sound' code in here ;)
// //
// (16Dec96 JEL) // (16Dec96 JEL)
// //
//-------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#include <stdio.h> #include <stdio.h>
#include "stdafx.h" #include "stdafx.h"
//#include "src\driver96.h"
#include "console.h" #include "console.h"
#include "defs.h" // for RESULT #include "defs.h" // for RESULT
#include "interpreter.h" #include "interpreter.h"
#include "protocol.h" // for FetchObjectName() for debugging FN_play_fx #include "protocol.h" // for FetchObjectName() for debugging FN_play_fx
#include "resman.h" #include "resman.h"
#include "sound.h" #include "sound.h"
#include "sword2.h" #include "sword2.h"
//-------------------------------------------------------------------------------------- typedef struct {
typedef struct uint32 resource; // resource id of sample
{ uint32 fetchId; // Id of resource in PSX CD queue. :)
uint32 resource; // resource id of sample uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM)
uint32 fetchId; // Id of resource in PSX CD queue. :) uint8 volume; // 0..16
uint16 delay; // cycles to wait before playing (or 'random chance' if FX_RANDOM) int8 pan; // -16..16
uint8 volume; // 0..16 uint8 type; // FX_SPOT, FX_RANDOM or FX_LOOP
int8 pan; // -16..16
uint8 type; // FX_SPOT, FX_RANDOM or FX_LOOP
} _fxq_entry; } _fxq_entry;
#define FXQ_LENGTH 32 // max number of fx in queue at once [DO NOT EXCEED 255] // max number of fx in queue at once [DO NOT EXCEED 255]
#define FXQ_LENGTH 32
_fxq_entry fxq[FXQ_LENGTH]; _fxq_entry fxq[FXQ_LENGTH];
//-------------------------------------------------------------------------------------- // used to store id of tunes that loop, for save & restore
uint32 looping_music_id=0;
uint32 looping_music_id=0; // used to store id of tunes that loop, for save & restore
char musicDirectory[120]; char musicDirectory[120];
//-------------------------------------------------------------------------------------- void Trigger_fx(uint8 j);
// local function prototypes
void Trigger_fx (uint8 j);
//--------------------------------------------------------------------------------------
// initialise the fxq by clearing all the entries // initialise the fxq by clearing all the entries
void Init_fx_queue(void) void Init_fx_queue(void) {
{ for (int j = 0; j < FXQ_LENGTH; j++) {
uint8 j; fxq[j].resource = 0; // 0 resource means 'empty' slot
fxq[j].fetchId = 0; // Not being fetched.
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 // process the fxq once every game cycle
void Process_fx_queue(void) void Process_fx_queue(void) {
{ for (int j = 0; j < FXQ_LENGTH; j++) {
uint8 j; // assuming FXQ_LENGTH is 255 or less if (!fxq[j].resource)
continue;
switch (fxq[j].type) {
case FX_RANDOM:
// 1 in 'delay' chance of this fx occurring
if (rand() % fxq[j].delay == 0)
Trigger_fx(j);
break;
for (j=0; j < FXQ_LENGTH; j++) // scan the queue case FX_SPOT:
{ if (fxq[j].delay)
if (fxq[j].resource) // if this entry isn't empty fxq[j].delay--;
{ else {
if (fxq[j].type == FX_RANDOM) // if it's type FX_RANDOM Trigger_fx(j);
{
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; fxq[j].type = FX_SPOT2;
} }
} break;
else if (fxq[j].type == FX_SPOT2)
{ case FX_SPOT2:
if (g_sound->IsFxOpen(j+1)) // Once the Fx has finished remove it from
fxq[j].resource = 0; // Once the Fx has finished remove it from the queue. // the queue.
}
if (g_sound->IsFxOpen(j + 1))
fxq[j].resource = 0;
break;
} }
} }
} }
//-------------------------------------------------------------------------------------- void Trigger_fx(uint8 j) { // called from Process_fx_queue only
void Trigger_fx(uint8 j) // called from Process_fx_queue only
{
uint8 *data; uint8 *data;
int32 id; int32 id;
uint32 rv; uint32 rv;
id = (uint32)j+1; // because 0 is not a valid id id = (uint32) j + 1; // because 0 is not a valid id
if (fxq[j].type == FX_SPOT) if (fxq[j].type == FX_SPOT) {
{ // load in the sample
data = res_man.Res_open(fxq[j].resource); // load in the sample data = res_man.Res_open(fxq[j].resource);
data += sizeof(_standardHeader); data += sizeof(_standardHeader);
rv = g_sound->PlayFx( id, data, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT ); // wav data gets copied to sound memory // wav data gets copied to sound memory
res_man.Res_close(fxq[j].resource); // release the sample rv = g_sound->PlayFx(id, data, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT);
// fxq[j].resource = 0; // clear spot fx from queue // release the sample
} res_man.Res_close(fxq[j].resource);
else // random & looped fx are already loaded into sound memory by FN_play_fx() } else {
{ // - to be referenced by 'j', so pass NULL data // 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) if (fxq[j].type == FX_RANDOM) {
rv = g_sound->PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT ); // not looped // Not looped
else // FX_LOOP rv = g_sound->PlayFx(id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXSPOT);
rv = g_sound->PlayFx( id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXLOOP ); // looped } else {
// Looped
rv = g_sound->PlayFx(id, NULL, fxq[j].volume, fxq[j].pan, RDSE_FXLOOP);
}
} }
#ifdef _SWORD2_DEBUG #ifdef _SWORD2_DEBUG
if (rv) if (rv)
Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__); Zdebug("SFX ERROR: PlayFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
#endif #endif
} }
//-------------------------------------------------------------------------------------- int32 FN_play_fx(int32 *params) { // called from script only
int32 FN_play_fx(int32 *params) // called from script only
{
// params: 0 sample resource id // params: 0 sample resource id
// 1 type (FX_SPOT, FX_RANDOM, FX_LOOP) // 1 type (FX_SPOT, FX_RANDOM, FX_LOOP)
// 2 delay (0..65535) // 2 delay (0..65535)
// 3 volume (0..16) // 3 volume (0..16)
// 4 pan (-16..16) // 4 pan (-16..16)
// example script: FN_play_fx (FXWATER, FX_LOOP, 0, 10, 15); // example script:
// fx_water = result; // fx_water is just a local script flag // FN_play_fx (FXWATER, FX_LOOP, 0, 10, 15);
// . // // fx_water is just a local script flag
// . // fx_water = result;
// . // .
// FN_stop_fx (fx_water); // .
// .
// FN_stop_fx (fx_water);
uint8 j=0; uint8 j = 0;
uint8 *data; uint8 *data;
uint32 id; uint32 id;
uint32 rv; uint32 rv;
//---------------------------------- #ifdef _SWORD2_DEBUG
#ifdef _SWORD2_DEBUG
_standardHeader *header; _standardHeader *header;
char type[10]; char type[10];
if (wantSfxDebug) {
if (wantSfxDebug)
{
switch (params[1]) // 'type' switch (params[1]) // 'type'
{ {
case FX_SPOT: case FX_SPOT:
strcpy(type,"SPOT"); strcpy(type, "SPOT");
break; break;
case FX_LOOP: case FX_LOOP:
strcpy(type,"LOOPED"); strcpy(type, "LOOPED");
break; break;
case FX_RANDOM: case FX_RANDOM:
strcpy(type,"RANDOM"); strcpy(type, "RANDOM");
break; break;
default: default:
strcpy(type,"INVALID"); 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); Zdebug("SFX (sample=\"%s\", vol=%d, pan=%d, delay=%d, type=%s)", FetchObjectName(params[0]), params[3], params[4], params[2], type);
} }
#endif
#endif //_SWORD2_DEBUG while (j < FXQ_LENGTH && fxq[j].resource != 0)
//----------------------------------
while ((j < FXQ_LENGTH) && (fxq[j].resource != 0))
j++; j++;
if (j==FXQ_LENGTH) if (j == FXQ_LENGTH)
{ return IR_CONT;
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].resource = params[0]; // wav resource id
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) fxq[j].type = params[1]; // FX_SPOT, FX_LOOP or FX_RANDOM
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 if (fxq[j].type == FX_RANDOM) {
fxq[j].pan = params[4]; // -16..16 // 'delay' param is the intended average no. seconds between
// playing this effect (+1 to avoid divide-by-zero in
// Process_fx_queue)
if (fxq[j].type == FX_SPOT) // spot fx fxq[j].delay = params[2] * 12 + 1;
{ } else {
#ifdef _SWORD2_DEBUG // FX_SPOT or FX_LOOP:
data = res_man.Res_open(fxq[j].resource); // "pre-load" the sample; this gets it into memory // 'delay' is no. frames to wait before playing
header = (_standardHeader*)data; fxq[j].delay = params[2];
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 _SWORD2_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 = g_sound->OpenFx(id,data); // copy it to sound memory, using position in queue as 'id'
#ifdef _SWORD2_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
}
} }
fxq[j].volume = params[3]; // 0..16
fxq[j].pan = params[4]; // -16..16
if (fxq[j].type == FX_SPOT) {
// "pre-load" the sample; this gets it into memory
data = res_man.Res_open(fxq[j].resource);
#ifdef _SWORD2_DEBUG
header = (_standardHeader*) data;
if (header->fileType != WAV_FILE)
Con_fatal_error("FN_play_fx given invalid resource (%s line %u)", __FILE__, __LINE__);
#endif
// but then releases it to "age" out if the space is needed
res_man.Res_close(fxq[j].resource);
} else {
// random & looped fx
id = (uint32) j + 1; // because 0 is not a valid id
// load in the sample
data = res_man.Res_open(fxq[j].resource);
#ifdef _SWORD2_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);
// copy it to sound memory, using position in queue as 'id'
rv = g_sound->OpenFx(id,data);
#ifdef _SWORD2_DEBUG
if (rv)
Zdebug("SFX ERROR: OpenFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
#endif
// release the sample
res_man.Res_close(fxq[j].resource);
}
//---------------------------------------------
// (James07uag97) // (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!
//---------------------------------------------
if (fxq[j].type == FX_LOOP) {
// play now, rather than in Process_fx_queue where it was
// getting played again & again!
Trigger_fx(j);
}
RESULT = j; // in case we want to call FN_stop_fx() later, to kill this fx (mainly for FX_LOOP & FX_RANDOM) // 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 RESULT = j;
return IR_CONT;
} }
//-------------------------------------------------------------------------------------- int32 FN_sound_fetch(int32 *params) {
int32 FN_sound_fetch(int32 *params)
{
return (IR_CONT); return (IR_CONT);
} }
//--------------------------------------------------------------------------------------
// to alter the volume and pan of a currently playing fx // to alter the volume and pan of a currently playing fx
int32 FN_set_fx_vol_and_pan(int32 *params) int32 FN_set_fx_vol_and_pan(int32 *params) {
{ // params: 0 id of fx (ie. the id returned in 'result' from
// params 0 id of fx (ie. the id returned in 'result' from FN_play_fx // FN_play_fx
// 1 new volume (0..16) // 1 new volume (0..16)
// 2 new pan (-16..16) // 2 new pan (-16..16)
// SetFxVolumePan(int32 id, uint8 vol, uint8 pan); // Zdebug("%d", params[2]);
g_sound->SetFxVolumePan(1+params[0], params[1], params[2]); // driver fx_id is 1+<pos in queue>
// Zdebug("%d",params[2]);
return (IR_CONT); // SetFxVolumePan(int32 id, uint8 vol, uint8 pan);
// driver fx_id is 1 + <pos in queue>
g_sound->SetFxVolumePan(1 + params[0], params[1], params[2]);
return IR_CONT;
} }
//--------------------------------------------------------------------------------------
// to alter the volume of a currently playing fx // to alter the volume of a currently playing fx
int32 FN_set_fx_vol(int32 *params) int32 FN_set_fx_vol(int32 *params) {
{ // params: 0 id of fx (ie. the id returned in 'result' from
// params 0 id of fx (ie. the id returned in 'result' from FN_play_fx // FN_play_fx
// 1 new volume (0..16) // 1 new volume (0..16)
// SetFxIdVolume(int32 id, uint8 vol); // SetFxIdVolume(int32 id, uint8 vol);
g_sound->SetFxIdVolume(1+params[0], params[1]); g_sound->SetFxIdVolume(1 + params[0], params[1]);
return IR_CONT;
return (IR_CONT);
} }
//--------------------------------------------------------------------------------------
int32 FN_stop_fx(int32 *params) // called from script only int32 FN_stop_fx(int32 *params) { // called from script only
{
// params: 0 position in queue // params: 0 position in queue
// This will stop looped & random fx instantly, and remove the fx from the queue. // This will stop looped & random fx instantly, and remove the fx
// So although it doesn't stop spot fx, it will remove them from the queue if they haven't yet played // 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]; uint8 j = (uint8) params[0];
uint32 id; uint32 id;
uint32 rv; uint32 rv;
if ((fxq[j].type == FX_RANDOM) || (fxq[j].type == FX_LOOP)) if (fxq[j].type == FX_RANDOM || fxq[j].type == FX_LOOP) {
{ id = (uint32) j + 1; // because 0 is not a valid id
id = (uint32)j+1; // because 0 is not a valid id
rv = g_sound->CloseFx(id); // stop fx & remove sample from sound memory
#ifdef _SWORD2_DEBUG // stop fx & remove sample from sound memory
rv = g_sound->CloseFx(id);
#ifdef _SWORD2_DEBUG
if (rv) if (rv)
Zdebug("SFX ERROR: CloseFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__); Zdebug("SFX ERROR: CloseFx() returned %.8x (%s line %u)", rv, __FILE__, __LINE__);
#endif #endif
} }
fxq[j].resource = 0; // remove from queue // remove from queue
fxq[j].resource = 0;
return IR_CONT;
return(IR_CONT); // continue script
} }
//-------------------------------------------------------------------------------------- int32 FN_stop_all_fx(int32 *params) { // called from script only
int32 FN_stop_all_fx(int32 *params) // called from script only
{
// Stops all looped & random fx and clears the entire queue // Stops all looped & random fx and clears the entire queue
// NO PARAMS // params: none
Clear_fx_queue(); Clear_fx_queue();
return IR_CONT;
return(IR_CONT); // continue script
} }
//--------------------------------------------------------------------------------------
// Stops all looped & random fx and clears the entire queue // Stops all looped & random fx and clears the entire queue
void Clear_fx_queue(void) void Clear_fx_queue(void) {
{ // stop all fx & remove the samples from sound memory
g_sound->ClearAllFx(); // stop all fx & remove the samples from sound memory g_sound->ClearAllFx();
Init_fx_queue(); // clean out the queue
// clean out the queue
Init_fx_queue();
} }
//-------------------------------------------------------------------------------------- // ===========================================================================
//=============================================================================
// int32 StreamMusic(uint8 *filename, int32 loopFlag) // int32 StreamMusic(uint8 *filename, int32 loopFlag)
// //
// Streams music from the file defined by filename. The loopFlag should // Streams music from the file defined by filename. The loopFlag should
@ -364,58 +348,59 @@ void Clear_fx_queue(void)
// Otherwise, it should be RDSE_FXSPOT. // Otherwise, it should be RDSE_FXSPOT.
// The return value must be checked for any problems. // The return value must be checked for any problems.
// //
// -------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// //
// int32 PauseMusic(void) // int32 PauseMusic(void)
// //
// Stops the music dead in it's tracks. // Stops the music dead in it's tracks.
// //
// -------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// //
// int32 UnpauseMusic(void) // int32 UnpauseMusic(void)
// //
// Re-starts the music from where it was stopped. // Re-starts the music from where it was stopped.
// //
//============================================================================= // ===========================================================================
int32 FN_prepare_music(int32 *params)
{ int32 FN_prepare_music(int32 *params) {
return (IR_CONT); return IR_CONT;
} }
//-------------------------------------------------------------------------------------- // Start a tune playing, to play once or to loop until stopped or next one
// Start a tune playing, to play once or to loop until stopped or next one played // 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]; int32 FN_play_music(int32 *params) { // updated by James on 10apr97
uint32 loopFlag; // params: 0 tune id
uint32 rv; // drivers return value // 1 loop flag (0 or 1)
char filename[128];
uint32 loopFlag;
uint32 rv;
// Zdebug("FN_play_music(%d)", params[0]); // Zdebug("FN_play_music(%d)", params[0]);
if (params[1]==FX_LOOP) // if it is to loop if (params[1] == FX_LOOP) {
{
loopFlag = RDSE_FXLOOP; 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
}
// keep a note of the id, for restarting after an
// interruption to gameplay
looping_music_id = params[0];
} else {
loopFlag = RDSE_FXSPOT;
// don't need to restart this tune after control panel or
// restore
looping_music_id = 0;
}
// add the appropriate file extension & play it // add the appropriate file extension & play it
if (g_sword2->_gameId == GID_SWORD2_DEMO) if (g_sword2->_gameId == GID_SWORD2_DEMO) {
// The demo I found didn't come with any music file, but you // The demo I found didn't come with any music file, but you
// could use the music from the first CD of the complete game, // could use the music from the first CD of the complete game,
// I suppose... // I suppose...
strcpy(filename, "music.clu"); strcpy(filename, "music.clu");
else { } else {
File f; File f;
sprintf(filename, "music%d.clu", res_man.WhichCd()); sprintf(filename, "music%d.clu", res_man.WhichCd());
@ -427,59 +412,49 @@ int32 FN_play_music(int32 *params) // updated by James on 10apr97
rv = g_sound->StreamCompMusic(filename, params[0], loopFlag); rv = g_sound->StreamCompMusic(filename, params[0], loopFlag);
#ifdef _SWORD2_DEBUG #ifdef _SWORD2_DEBUG
if (rv) if (rv)
Zdebug("ERROR: StreamCompMusic(%s, %d, %d) returned error 0x%.8x", filename, params[0], loopFlag, rv); Zdebug("ERROR: StreamCompMusic(%s, %d, %d) returned error 0x%.8x", filename, params[0], loopFlag, rv);
#endif #endif
// Zdebug("FN_play_music(%d) returning", params[0]); // Zdebug("FN_play_music(%d) returning", params[0]);
return(IR_CONT); // continue script return IR_CONT;
} }
//-------------------------------------------------------------------------------------- int32 FN_stop_music(int32 *params) { // called from script only
int32 FN_stop_music(int32 *params) // called from script only
{
// params: none // params: none
looping_music_id = 0; // clear the 'looping' flag
looping_music_id=0; // clear the 'looping' flag
g_sound->StopMusic(); g_sound->StopMusic();
return IR_CONT;
if (params);
return(IR_CONT); // continue script
} }
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
void Kill_music(void) // James22aug97
{
uint8 count;
looping_music_id=0; // clear the 'looping' flag void Kill_music(void) { // James22aug97
looping_music_id = 0; // clear the 'looping' flag
g_sound->StopMusic(); g_sound->StopMusic();
/* I don't think this is needed with our music code
// THIS BIT CAUSES THE MUSIC TO STOP INSTANTLY! // THIS BIT CAUSES THE MUSIC TO STOP INSTANTLY!
for(count=0; count<16; count++) for(int count=0; count<16; count++)
g_sound->UpdateCompSampleStreaming(); g_sound->UpdateCompSampleStreaming();
*/
} }
//--------------------------------------------------------------------------------------
int32 FN_check_music_playing(int32 *params) // James (30july97)
{
// params: none int32 FN_check_music_playing(int32 *params) { // James (30july97)
// params: none
// sets result to no. of seconds of current tune remaining // sets result to no. of seconds of current tune remaining
// or 0 if no music playing // or 0 if no music playing
RESULT = g_sound->MusicTimeRemaining(); // in seconds, rounded up to the nearest second // in seconds, rounded up to the nearest second
RESULT = g_sound->MusicTimeRemaining();
return(IR_CONT); // continue script return IR_CONT;
} }
//--------------------------------------------------------------------------------------
void PauseAllSound(void) // James25july97 void PauseAllSound(void) { // James25july97
{ uint32 rv;
uint32 rv; // for drivers return value
rv = g_sound->PauseMusic(); rv = g_sound->PauseMusic();
if (rv != RD_OK) if (rv != RD_OK)
@ -493,10 +468,9 @@ void PauseAllSound(void) // James25july97
if (rv != RD_OK) if (rv != RD_OK)
Zdebug("ERROR: PauseFx() returned %.8x in PauseAllSound()", rv); Zdebug("ERROR: PauseFx() returned %.8x in PauseAllSound()", rv);
} }
//--------------------------------------------------------------------------------------
void UnpauseAllSound(void) // James25july97 void UnpauseAllSound(void) { // James25july97
{ uint32 rv;
uint32 rv; // for drivers return value
rv = g_sound->UnpauseMusic(); rv = g_sound->UnpauseMusic();
if (rv != RD_OK) if (rv != RD_OK)
@ -510,5 +484,3 @@ void UnpauseAllSound(void) // James25july97
if (rv != RD_OK) if (rv != RD_OK)
Zdebug("ERROR: UnpauseFx() returned %.8x in UnpauseAllSound()", rv); Zdebug("ERROR: UnpauseFx() returned %.8x in UnpauseAllSound()", rv);
} }
//--------------------------------------------------------------------------------------

View file

@ -33,23 +33,30 @@
#include "common/scummsys.h" #include "common/scummsys.h"
// fx types // fx types
#define FX_SPOT 0 #define FX_SPOT 0
#define FX_LOOP 1 #define FX_LOOP 1
#define FX_RANDOM 2 #define FX_RANDOM 2
#define FX_SPOT2 3 #define FX_SPOT2 3
void Init_fx_queue(void); // to be called during system initialisation // to be called during system initialisation
void Process_fx_queue(void); // to be called from the main loop, once per cycle void Init_fx_queue(void);
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 // to be called from the main loop, once per cycle
void Process_fx_queue(void);
// stops all fx & clears the queue - eg. when leaving a location
void Clear_fx_queue(void);
void PauseAllSound(void);
void UnpauseAllSound(void);
void Kill_music(void);
int32 FN_play_music(int32 *params); // for save_Rest.cpp int32 FN_play_music(int32 *params); // for save_Rest.cpp
int32 FN_stop_music(int32 *params); int32 FN_stop_music(int32 *params);
extern uint32 looping_music_id; // used to store id of tunes that loop, for save & restore // used to store id of tunes that loop, for save & restore
extern uint32 looping_music_id;
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -20,25 +20,26 @@
#ifndef _SPEECH #ifndef _SPEECH
#define _SPEECH #define _SPEECH
//#include "src\driver96.h"
#include "header.h" #include "header.h"
#define MAX_SUBJECT_LIST 30 // is that enough?
#define MAX_SUBJECT_LIST 30 //is that enough? // array of these for subject menu build up
typedef struct {
uint32 res;
uint32 ref;
typedef struct //array of these for subject menu build up
{
uint32 res;
uint32 ref;
} _subject_unit; } _subject_unit;
extern uint32 speech_text_bloc_no; // so speech text cleared when running a new start-script // so speech text cleared when running a new start-script
extern int16 officialTextNumber; extern uint32 speech_text_bloc_no;
extern int32 speechScriptWaiting; extern int16 officialTextNumber;
extern int32 speechScriptWaiting;
//could alternately use logic->looping of course
extern int choosing;
extern uint32 unpause_zone;
extern int choosing; //could alternately use logic->looping of course
extern uint32 unpause_zone;
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -20,15 +20,11 @@
#ifndef _WALKER #ifndef _WALKER
#define _WALKER #define _WALKER
//#include "src\driver96.h"
int32 FN_face_mega(int32 *params); int32 FN_face_mega(int32 *params);
int32 FN_turn(int32 *params); int32 FN_turn(int32 *params);
int32 FN_walk(int32 *params); // James (14nov96) int32 FN_walk(int32 *params);
int32 FN_walk_to_anim(int32 *params); // James (14nov96) int32 FN_walk_to_anim(int32 *params);
int32 FN_stand_after_anim(int32 *params); // James (18jun97) int32 FN_stand_after_anim(int32 *params);
int32 FN_stand(int32 *params); // James int32 FN_stand(int32 *params);
#endif #endif