Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,197 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "scumm/he/intern_he.h"
#ifdef USE_ENET
#include "scumm/he/net/net_main.h"
#ifdef USE_BASIC_NET
#include "scumm/he/net/net_lobby.h"
#endif
#include "scumm/he/net/net_defines.h"
#endif
#include "scumm/he/logic_he.h"
// DirectPlay opcodes:
#define OP_NET_REMOTE_START_SCRIPT 1492
#define OP_NET_QUERY_PROVIDERS 1497
#define OP_NET_CLOSE_PROVIDER 1500
#define OP_NET_QUERY_SESSIONS 1501
#define OP_NET_GET_SESSION_NAME 1502
#define OP_NET_JOIN_SESSION 1504
#define OP_NET_END_SESSION 1505
#define OP_NET_ADD_USER 1506
#define OP_NET_WHO_SENT_THIS 1508
#define OP_NET_REMOTE_SEND_ARRAY 1509
#define OP_NET_INIT 1513
#define OP_NET_WHO_AM_I 1510
#define OP_NET_INIT_LAN_GAME 1515
#define OP_NET_SET_PROVIDER_BY_NAME 1516
// MAIA (Updater) opcodes.
#define OP_NET_CHECK_INTERNET_STATUS 3001
#define OP_NET_SHUT_DOWN_MAIA 3004
namespace Scumm {
/**
* Logic code for:
* Backyard Baseball 2001
*/
class LogicHEbaseball2001 : public LogicHE {
public:
LogicHEbaseball2001(ScummEngine_v90he *vm) : LogicHE(vm) {}
int versionID() override;
int startOfFrame() override;
int32 dispatch(int op, int numArgs, int32 *args) override;
protected:
#ifdef USE_ENET
void netRemoteStartScript(int numArgs, int32 *args);
void netRemoteSendArray(int32 *args);
#endif
};
int LogicHEbaseball2001::versionID() {
return 1;
}
int LogicHEbaseball2001::startOfFrame() {
#ifdef USE_ENET
#ifdef USE_BASIC_NET
_vm->_lobby->doNetworkOnceAFrame();
#endif
_vm->_net->doNetworkOnceAFrame(15);
#endif
return 0;
}
int32 LogicHEbaseball2001::dispatch(int op, int numArgs, int32 *args) {
#if defined(USE_ENET) && defined(USE_BASIC_NET)
if (op > 2120 && op < 3003 && op != OP_NET_CHECK_INTERNET_STATUS)
return _vm->_lobby->dispatch(op, numArgs, args);
#endif
int res = 0;
switch (op) {
case OP_NET_INIT:
// Initialize network system, this gets called at boot up and
// sets VAR_NETWORK_AVAILABLE (100). We just return a 1 if
// ENet is compiled.
#ifdef USE_ENET
res = 1;
#endif
break;
#ifdef USE_ENET
case OP_NET_REMOTE_START_SCRIPT:
netRemoteStartScript(numArgs, args);
break;
case OP_NET_CLOSE_PROVIDER:
_vm->_net->closeProvider();
break;
case OP_NET_QUERY_SESSIONS:
#ifdef USE_BASIC_NET
if (_vm->_lobby->_sessionId) {
_vm->_net->querySessions();
// Only proceed if we've found the session
// we're looking for.
res = _vm->_net->ifSessionExist(_vm->_lobby->_sessionId);
}
#endif
break;
case OP_NET_JOIN_SESSION:
#ifdef USE_BASIC_NET
if (_vm->_lobby->_sessionId) {
res = _vm->_net->joinSessionById(_vm->_lobby->_sessionId);
if (res) {
_vm->_net->stopQuerySessions();
}
}
#endif
break;
case OP_NET_END_SESSION:
res = _vm->_net->endSession();
break;
case OP_NET_ADD_USER:
char userName[MAX_PLAYER_NAME];
_vm->getStringFromArray(args[0], userName, sizeof(userName));
res = _vm->_net->addUser(userName, userName);
break;
case OP_NET_WHO_SENT_THIS:
res = _vm->_net->whoSentThis();
break;
case OP_NET_REMOTE_SEND_ARRAY:
netRemoteSendArray(args);
break;
case OP_NET_WHO_AM_I:
res = _vm->_net->whoAmI();
break;
#endif // USE_ENET
case OP_NET_CHECK_INTERNET_STATUS:
#if defined(USE_ENET) && defined(USE_BASIC_NET)
// We can only use the lobby system if both
// libcurl (for lobby communication) and
// ENet (for gameplay communication) is enabled.
// TODO: Actually check if we're connected to the
// Internet.
res = 1;
#endif
break;
case OP_NET_SHUT_DOWN_MAIA:
break;
default:
LogicHE::dispatch(op, numArgs, args);
}
return res;
}
#ifdef USE_ENET
void LogicHEbaseball2001::netRemoteStartScript(int numArgs, int32 *args) {
_vm->_net->remoteStartScript(args[0], args[1], args[2], numArgs - 3, &args[3]);
}
void LogicHEbaseball2001::netRemoteSendArray(int32 *args) {
_vm->_net->remoteSendArray(args[0], args[1], args[2], args[3]);
}
#endif // USE_ENET
LogicHE *makeLogicHEbaseball2001(ScummEngine_v90he *vm) {
return new LogicHEbaseball2001(vm);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,675 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/basketball/basketball.h"
#include "scumm/he/basketball/collision/bball_collision.h"
#include "scumm/he/basketball/geo_translations.h"
namespace Scumm {
// Opcodes
#define WORLD_TO_SCREEN_TRANSLATION 1006
#define WORLD_TO_SCREEN_TRANSLATION_PARAMS 3
#define SCREEN_TO_WORLD_TRANSLATION 1010
#define SCREEN_TO_WORLD_TRANSLATION_PARAMS 2
#define INIT_SCREEN_TRANSLATIONS 1011
#define INIT_SCREEN_TRANSLATIONS_PARAMS 0
#define GET_COURT_DIMENSIONS 1012
#define GET_COURT_DIMENSIONS_PARAMS 0
#define COMPUTE_INITIAL_SHOT_VELOCITY 1030
#define COMPUTE_INITIAL_SHOT_VELOCITY_PARAMS 4
#define COMPUTE_TRAJECTORY_TO_TARGET 1031
#define COMPUTE_TRAJECTORY_TO_TARGET_PARAMS 7
#define COMPUTE_LAUNCH_TRAJECTORY 1032
#define COMPUTE_LAUNCH_TRAJECTORY_PARAMS 6
#define COMPUTE_ANGLE_OF_SHOT 1033
#define COMPUTE_ANGLE_OF_SHOT_PARAMS 2
#define COMPUTE_ANGLE_OF_PASS 1034
#define COMPUTE_ANGLE_OF_PASS_PARAMS 4
#define COMPUTE_POINTS_FOR_PIXELS 1035
#define COMPUTE_POINTS_FOR_PIXELS_PARAMS 2
#define COMPUTE_ANGLE_OF_BOUNCE_PASS 1036
#define COMPUTE_ANGLE_OF_BOUNCE_PASS_PARAMS 5
#define COMPUTE_BANK_SHOT_TARGET 1037
#define COMPUTE_BANK_SHOT_TARGET_PARAMS 4
#define COMPUTE_SWOOSH_TARGET 1038
#define COMPUTE_SWOOSH_TARGET_PARAMS 4
#define DETECT_SHOT_MADE 1039
#define DETECT_SHOT_MADE_PARAMS 9
#define COMPUTE_ANGLE_BETWEEN_VECTORS 1040
#define COMPUTE_ANGLE_BETWEEN_VECTORS_PARAMS 6
#define HIT_MOVING_TARGET 1041
#define HIT_MOVING_TARGET_PARAMS 7
#define GET_PASS_TARGET 1042
#define GET_PASS_TARGET_PARAMS 3
#define DETECT_PASS_BLOCKER 1043
#define DETECT_PASS_BLOCKER_PARAMS 3
#define GET_BALL_INTERCEPT 1044
#define GET_BALL_INTERCEPT_PARAMS 4
#define INIT_COURT 1050
#define INIT_COURT_PARAMS 1
#define INIT_BALL 1051
#define INIT_BALL_PARAMS 8
#define INIT_PLAYER 1052
#define INIT_PLAYER_PARAMS 7
#define DEINIT_COURT 1053
#define DEINIT_COURT_PARAMS 0
#define DEINIT_BALL 1054
#define DEINIT_BALL_PARAMS 0
#define DEINIT_PLAYER 1055
#define DEINIT_PLAYER_PARAMS 1
#define DETECT_BALL_COLLISION 1056
#define DETECT_BALL_COLLISION_PARAMS 8
#define DETECT_PLAYER_COLLISION 1057
#define DETECT_PLAYER_COLLISION_PARAMS 8
#define GET_LAST_BALL_COLLISION 1058
#define GET_LAST_BALL_COLLISION_PARAMS 1
#define GET_LAST_PLAYER_COLLISION 1059
#define GET_LAST_PLAYER_COLLISION_PARAMS 1
#define INIT_VIRTUAL_BALL 1060
#define INIT_VIRTUAL_BALL_PARAMS 8
#define DEINIT_VIRTUAL_BALL 1061
#define DEINIT_VIRTUAL_BALL_PARAMS 0
#define PLAYER_OFF 1062
#define PLAYER_OFF_PARAMS 1
#define PLAYER_ON 1063
#define PLAYER_ON_PARAMS 1
#define RAISE_SHIELDS 1064
#define RAISE_SHIELDS_PARAMS 1
#define LOWER_SHIELDS 1065
#define LOWER_SHIELDS_PARAMS 1
#define FIND_PLAYER_CLOSEST_TO_BALL 1066
#define FIND_PLAYER_CLOSEST_TO_BALL_PARAMS 1
#define IS_PLAYER_IN_BOUNDS 1067
#define IS_PLAYER_IN_BOUNDS_PARAMS 1
#define ARE_SHIELDS_CLEAR 1068
#define ARE_SHIELDS_CLEAR_PARAMS 0
#define SHIELD_PLAYER 1069
#define SHIELD_PLAYER_PARAMS 2
#define CLEAR_PLAYER_SHIELD 1070
#define CLEAR_PLAYER_SHIELD_PARAMS 1
#define IS_BALL_IN_BOUNDS 1071
#define IS_BALL_IN_BOUNDS_PARAMS 0
#define GET_AVOIDANCE_PATH 1072
#define GET_AVOIDANCE_PATH_PARAMS 4
#define SET_BALL_LOCATION 1073
#define SET_BALL_LOCATION_PARAMS 4
#define GET_BALL_LOCATION 1074
#define GET_BALL_LOCATION_PARAMS 1
#define SET_PLAYER_LOCATION 1075
#define SET_PLAYER_LOCATION_PARAMS 4
#define GET_PLAYER_LOCATION 1076
#define GET_PLAYER_LOCATION_PARAMS 1
#define START_BLOCK 1077
#define START_BLOCK_PARAMS 3
#define HOLD_BLOCK 1078
#define HOLD_BLOCK_PARAMS 1
#define END_BLOCK 1079
#define END_BLOCK_PARAMS 1
#define IS_PLAYER_IN_GAME 1080
#define IS_PLAYER_IN_GAME_PARAMS 1
#define IS_BALL_IN_GAME 1081
#define IS_BALL_IN_GAME_PARAMS 1
#define UPDATE_CURSOR_POS 1090
#define UPDATE_CURSOR_POS_PARAMS 2
#define MAKE_CURSOR_STICKY 1091
#define MAKE_CURSOR_STICKY_PARAMS 2
#define CURSOR_TRACK_MOVING_OBJECT 1092
#define CURSOR_TRACK_MOVING_OBJECT_PARAMS 2
#define GET_CURSOR_POSITION 1093
#define GET_CURSOR_POSITION_PARAMS 0
#define AI_GET_OPEN_SPOT 1100
#define AI_GET_OPEN_SPOT_PARAMS 10
#define AI_GET_OPPONENTS_IN_CONE 1101
#define AI_GET_OPPONENTS_IN_CONE_PARAMS 6
#define U32_CLEAN_UP_OFF_HEAP 1102
#define U32_CLEAN_UP_OFF_HEAP_PARAMS 0
#define DRAW_DEBUG_LINES 1500
#define DRAW_DEBUG_LINES_PARAMS 0
#define ADD_DEBUG_GEOM 1501
int LogicHEBasketball::versionID() {
return 1;
}
int32 LogicHEBasketball::dispatch(int cmdID, int paramCount, int32 *params) {
U32FltPoint3D flt3DPoint1, flt3DPoint2;
U32FltPoint2D flt2DPoint1, flt2DPoint2;
U32IntVector3D int3DVector1;
U32FltVector3D flt3DVector1, flt3DVector2;
U32FltVector2D flt2DVector1;
U32Sphere sphere1;
int retValue = 0;
switch (cmdID) {
case INIT_SCREEN_TRANSLATIONS:
assert(paramCount == INIT_SCREEN_TRANSLATIONS_PARAMS);
retValue = u32_userInitScreenTranslations();
break;
case WORLD_TO_SCREEN_TRANSLATION:
assert(paramCount == WORLD_TO_SCREEN_TRANSLATION_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
retValue = u32_userWorldToScreenTranslation(flt3DPoint1);
break;
case SCREEN_TO_WORLD_TRANSLATION:
assert(paramCount == SCREEN_TO_WORLD_TRANSLATION_PARAMS);
flt2DPoint1.x = (float)params[0];
flt2DPoint1.y = (float)params[1];
retValue = u32_userScreenToWorldTranslation(flt2DPoint1);
break;
case GET_COURT_DIMENSIONS:
assert(paramCount == GET_COURT_DIMENSIONS_PARAMS);
retValue = u32_userGetCourtDimensions();
break;
case COMPUTE_TRAJECTORY_TO_TARGET:
assert(paramCount == COMPUTE_TRAJECTORY_TO_TARGET_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
flt3DPoint2.x = (float)params[3];
flt3DPoint2.y = (float)params[4];
flt3DPoint2.z = (float)params[5];
retValue = u32_userComputeTrajectoryToTarget(flt3DPoint1, flt3DPoint2, params[6]);
break;
case COMPUTE_LAUNCH_TRAJECTORY:
assert(paramCount == COMPUTE_LAUNCH_TRAJECTORY_PARAMS);
flt2DPoint1.x = (float)params[0];
flt2DPoint1.y = (float)params[1];
flt2DPoint2.x = (float)params[2];
flt2DPoint2.y = (float)params[3];
retValue = u32_userComputeLaunchTrajectory(flt2DPoint1, flt2DPoint2, params[4], params[5]);
break;
case COMPUTE_ANGLE_BETWEEN_VECTORS:
assert(paramCount == COMPUTE_ANGLE_BETWEEN_VECTORS_PARAMS);
flt3DVector1.x = (float)params[0];
flt3DVector1.y = (float)params[1];
flt3DVector1.z = (float)params[2];
flt3DVector2.x = (float)params[3];
flt3DVector2.y = (float)params[4];
flt3DVector2.z = (float)params[5];
retValue = u32_userComputeAngleBetweenVectors(flt3DVector1, flt3DVector2);
break;
case COMPUTE_INITIAL_SHOT_VELOCITY:
assert(paramCount == COMPUTE_INITIAL_SHOT_VELOCITY_PARAMS);
retValue = u32_userComputeInitialShotVelocity(params[0], params[1], params[2], params[3]);
break;
case COMPUTE_ANGLE_OF_SHOT:
assert(paramCount == COMPUTE_ANGLE_OF_SHOT_PARAMS);
retValue = u32_userComputeAngleOfShot(params[0], params[1]);
break;
case COMPUTE_ANGLE_OF_PASS:
assert(paramCount == COMPUTE_ANGLE_OF_PASS_PARAMS);
retValue = u32_userComputeAngleOfPass(params[0], params[1], params[2], params[3]);
break;
case COMPUTE_ANGLE_OF_BOUNCE_PASS:
assert(paramCount == COMPUTE_ANGLE_OF_BOUNCE_PASS_PARAMS);
retValue = u32_userComputeAngleOfBouncePass(params[0], params[1], params[2], params[3], params[4]);
break;
case HIT_MOVING_TARGET:
assert(paramCount == HIT_MOVING_TARGET_PARAMS);
flt2DPoint1.x = (float)params[0];
flt2DPoint1.y = (float)params[1];
flt2DPoint2.x = (float)params[2];
flt2DPoint2.y = (float)params[3];
flt2DVector1.x = (float)params[4];
flt2DVector1.y = (float)params[5];
retValue = u32_userHitMovingTarget(flt2DPoint1, flt2DPoint2, flt2DVector1, params[6]);
break;
case GET_PASS_TARGET:
assert(paramCount == GET_PASS_TARGET_PARAMS);
flt3DVector1.x = (float)params[1];
flt3DVector1.y = (float)params[2];
retValue = u32_userGetPassTarget(params[0], flt3DVector1);
break;
case DETECT_PASS_BLOCKER:
assert(paramCount == DETECT_PASS_BLOCKER_PARAMS);
flt3DVector1.x = (float)params[1];
flt3DVector1.y = (float)params[2];
retValue = u32_userDetectPassBlocker(params[0], flt3DVector1);
break;
case GET_BALL_INTERCEPT:
assert(paramCount == GET_BALL_INTERCEPT_PARAMS);
retValue = u32_userGetBallIntercept(params[0], params[1], params[2], params[3]);
break;
case COMPUTE_POINTS_FOR_PIXELS:
assert(paramCount == COMPUTE_POINTS_FOR_PIXELS_PARAMS);
retValue = u32_userComputePointsForPixels(params[0], params[1]);
break;
case COMPUTE_BANK_SHOT_TARGET:
assert(paramCount == COMPUTE_BANK_SHOT_TARGET_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
retValue = u32_userComputeBankShotTarget(flt3DPoint1, params[3]);
break;
case COMPUTE_SWOOSH_TARGET:
assert(paramCount == COMPUTE_SWOOSH_TARGET_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
retValue = u32_userComputeSwooshTarget(flt3DPoint1, params[3]);
break;
case INIT_COURT:
assert(paramCount == INIT_COURT_PARAMS);
retValue = u32_userInitCourt(params[0]);
break;
case DEINIT_COURT:
assert(paramCount == DEINIT_COURT_PARAMS);
retValue = u32_userDeinitCourt();
break;
case INIT_BALL:
assert(paramCount == INIT_BALL_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
flt3DVector1.x = (float)params[3];
flt3DVector1.y = (float)params[4];
flt3DVector1.z = (float)params[5];
retValue = u32_userInitBall(flt3DPoint1, flt3DVector1, params[6], params[7]);
break;
case DEINIT_BALL:
assert(paramCount == DEINIT_BALL_PARAMS);
retValue = u32_userDeinitBall();
break;
case INIT_VIRTUAL_BALL:
assert(paramCount == INIT_VIRTUAL_BALL_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
flt3DVector1.x = (float)params[3];
flt3DVector1.y = (float)params[4];
flt3DVector1.z = (float)params[5];
retValue = u32_userInitVirtualBall(flt3DPoint1, flt3DVector1, params[6], params[7]);
break;
case DEINIT_VIRTUAL_BALL:
assert(paramCount == DEINIT_VIRTUAL_BALL_PARAMS);
retValue = u32_userDeinitVirtualBall();
break;
case INIT_PLAYER:
assert(paramCount == INIT_PLAYER_PARAMS);
flt3DPoint1.x = (float)params[1];
flt3DPoint1.y = (float)params[2];
flt3DPoint1.z = (float)params[3];
retValue = u32_userInitPlayer(params[0], flt3DPoint1, params[4], params[5], (params[6] != 0));
break;
case DEINIT_PLAYER:
assert(paramCount == DEINIT_PLAYER_PARAMS);
retValue = u32_userDeinitPlayer(params[0]);
break;
case PLAYER_OFF:
assert(paramCount == PLAYER_OFF_PARAMS);
retValue = u32_userPlayerOff(params[0]);
break;
case PLAYER_ON:
assert(paramCount == PLAYER_ON_PARAMS);
retValue = u32_userPlayerOn(params[0]);
break;
case SET_BALL_LOCATION:
assert(paramCount == SET_BALL_LOCATION_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
_vm->_basketball->_court->getBallPtr(params[3])->center = flt3DPoint1;
retValue = 1;
break;
case GET_BALL_LOCATION:
assert(paramCount == GET_BALL_LOCATION_PARAMS);
flt3DPoint1 = _vm->_basketball->_court->getBallPtr(params[0])->center;
writeScummVar(_vm1->VAR_U32_USER_VAR_A, _vm->_basketball->u32FloatToInt(flt3DPoint1.x));
writeScummVar(_vm1->VAR_U32_USER_VAR_B, _vm->_basketball->u32FloatToInt(flt3DPoint1.y));
writeScummVar(_vm1->VAR_U32_USER_VAR_C, _vm->_basketball->u32FloatToInt(flt3DPoint1.z));
retValue = 1;
break;
case SET_PLAYER_LOCATION:
assert(paramCount == SET_PLAYER_LOCATION_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
flt3DPoint1.z += (_vm->_basketball->_court->getPlayerPtr(params[3])->height / 2);
_vm->_basketball->_court->getPlayerPtr(params[3])->center = flt3DPoint1;
retValue = 1;
break;
case GET_PLAYER_LOCATION:
assert(paramCount == GET_PLAYER_LOCATION_PARAMS);
flt3DPoint1 = _vm->_basketball->_court->getPlayerPtr(params[0])->center;
flt3DPoint1.z -= (_vm->_basketball->_court->getPlayerPtr(params[0])->height / 2);
writeScummVar(_vm1->VAR_U32_USER_VAR_A, _vm->_basketball->u32FloatToInt(flt3DPoint1.x));
writeScummVar(_vm1->VAR_U32_USER_VAR_B, _vm->_basketball->u32FloatToInt(flt3DPoint1.y));
writeScummVar(_vm1->VAR_U32_USER_VAR_C, _vm->_basketball->u32FloatToInt(flt3DPoint1.z));
retValue = 1;
break;
case DETECT_BALL_COLLISION:
assert(paramCount == DETECT_BALL_COLLISION_PARAMS);
flt3DPoint1.x = (float)params[0];
flt3DPoint1.y = (float)params[1];
flt3DPoint1.z = (float)params[2];
flt3DVector1.x = (float)params[3];
flt3DVector1.y = (float)params[4];
flt3DVector1.z = (float)params[5];
retValue = u32_userDetectBallCollision(flt3DPoint1, flt3DVector1, params[6], params[7]);
break;
case DETECT_PLAYER_COLLISION:
assert(paramCount == DETECT_PLAYER_COLLISION_PARAMS);
flt3DPoint1.x = (float)params[1];
flt3DPoint1.y = (float)params[2];
flt3DPoint1.z = (float)params[3];
flt3DVector1.x = (float)params[4];
flt3DVector1.y = (float)params[5];
flt3DVector1.z = (float)params[6];
retValue = u32_userDetectPlayerCollision(params[0], flt3DPoint1, flt3DVector1, (params[7] != 0));
break;
case GET_LAST_BALL_COLLISION:
assert(paramCount == GET_LAST_BALL_COLLISION_PARAMS);
retValue = u32_userGetLastBallCollision(params[0]);
break;
case GET_LAST_PLAYER_COLLISION:
assert(paramCount == GET_LAST_PLAYER_COLLISION_PARAMS);
retValue = u32_userGetLastPlayerCollision(params[0]);
break;
case DETECT_SHOT_MADE:
assert(paramCount == DETECT_SHOT_MADE_PARAMS);
sphere1.center.x = (float)params[0];
sphere1.center.y = (float)params[1];
sphere1.center.z = (float)params[2];
sphere1.radius = (float)params[6];
int3DVector1.x = params[3];
int3DVector1.y = params[4];
int3DVector1.z = params[5];
retValue = u32_userDetectShotMade(sphere1, int3DVector1, params[7], params[8]);
break;
case RAISE_SHIELDS:
assert(paramCount == RAISE_SHIELDS_PARAMS);
retValue = u32_userRaiseShields(params[0]);
break;
case LOWER_SHIELDS:
assert(paramCount == LOWER_SHIELDS_PARAMS);
retValue = u32_userLowerShields(params[0]);
break;
case FIND_PLAYER_CLOSEST_TO_BALL:
assert((paramCount == 0) || (paramCount == FIND_PLAYER_CLOSEST_TO_BALL_PARAMS));
if (paramCount == 0) {
retValue = u32_userGetPlayerClosestToBall();
} else {
retValue = u32_userGetPlayerClosestToBall(params[0]);
}
break;
case IS_PLAYER_IN_BOUNDS:
assert(paramCount == IS_PLAYER_IN_BOUNDS_PARAMS);
retValue = u32_userIsPlayerInBounds(params[0]);
break;
case IS_BALL_IN_BOUNDS:
assert(paramCount == IS_BALL_IN_BOUNDS_PARAMS);
retValue = u32_userIsBallInBounds();
break;
case ARE_SHIELDS_CLEAR:
assert(paramCount == ARE_SHIELDS_CLEAR_PARAMS);
retValue = u32_userAreShieldsClear();
break;
case SHIELD_PLAYER:
assert(paramCount == SHIELD_PLAYER_PARAMS);
retValue = u32_userShieldPlayer(params[0], params[1]);
break;
case CLEAR_PLAYER_SHIELD:
assert(paramCount == CLEAR_PLAYER_SHIELD_PARAMS);
retValue = u32_userClearPlayerShield(params[0]);
break;
case GET_AVOIDANCE_PATH:
assert(paramCount == GET_AVOIDANCE_PATH_PARAMS);
flt2DPoint1.x = (float)params[1];
flt2DPoint1.y = (float)params[2];
retValue = u32_userGetAvoidancePath(params[0], flt2DPoint1, (EAvoidanceType)params[3]);
break;
case START_BLOCK:
assert(paramCount == START_BLOCK_PARAMS);
assert((FIRST_PLAYER <= params[0]) && (params[0] <= LAST_PLAYER));
(_vm->_basketball->_court->getPlayerPtr(params[0]))->startBlocking(params[1], params[2]);
retValue = 1;
break;
case HOLD_BLOCK:
assert(paramCount == HOLD_BLOCK_PARAMS);
assert((FIRST_PLAYER <= params[0]) && (params[0] <= LAST_PLAYER));
(_vm->_basketball->_court->getPlayerPtr(params[0]))->holdBlocking();
retValue = 1;
break;
case END_BLOCK:
assert(paramCount == END_BLOCK_PARAMS);
assert((FIRST_PLAYER <= params[0]) && (params[0] <= LAST_PLAYER));
(_vm->_basketball->_court->getPlayerPtr(params[0]))->endBlocking();
retValue = 1;
break;
case IS_PLAYER_IN_GAME:
assert(paramCount == IS_PLAYER_IN_GAME_PARAMS);
assert((FIRST_PLAYER <= params[0]) && (params[0] <= LAST_PLAYER));
writeScummVar(_vm1->VAR_U32_USER_VAR_A, ((_vm->_basketball->_court->getPlayerPtr(params[0]))->_playerIsInGame) ? 1 : 0);
retValue = 1;
break;
case IS_BALL_IN_GAME:
assert(paramCount == IS_BALL_IN_GAME_PARAMS);
writeScummVar(_vm1->VAR_U32_USER_VAR_A, ((_vm->_basketball->_court->getBallPtr(params[0]))->_ignore) ? 0 : 1);
retValue = 1;
break;
case UPDATE_CURSOR_POS:
assert(paramCount == UPDATE_CURSOR_POS_PARAMS);
retValue = u32_userUpdateCursorPos(params[0], params[1]);
break;
case MAKE_CURSOR_STICKY:
assert(paramCount == MAKE_CURSOR_STICKY_PARAMS);
retValue = u32_userMakeCursorSticky(params[0], params[1]);
break;
case CURSOR_TRACK_MOVING_OBJECT:
assert(paramCount == CURSOR_TRACK_MOVING_OBJECT_PARAMS);
retValue = u32_userCursorTrackMovingObject(params[0], params[1]);
break;
case GET_CURSOR_POSITION:
assert(paramCount == GET_CURSOR_POSITION_PARAMS);
retValue = u32_userGetCursorPos();
break;
case AI_GET_OPEN_SPOT:
assert(paramCount == AI_GET_OPEN_SPOT_PARAMS);
retValue = u32_userGetOpenSpot(
params[0],
U32FltVector2D((float)params[1], (float)params[2]),
U32FltVector2D((float)params[3], (float)params[4]),
U32FltVector2D((float)params[5], (float)params[6]),
(params[7] != 0),
U32FltVector2D((float)params[8], (float)params[9]));
break;
case AI_GET_OPPONENTS_IN_CONE:
assert(paramCount == AI_GET_OPPONENTS_IN_CONE_PARAMS);
retValue = _vm->_basketball->numOpponentsInCone(
params[0],
(((float)params[1]) / 65536),
U32FltVector2D((float)params[2], (float)params[3]),
U32FltVector2D((float)params[4], (float)params[5]));
break;
case U32_CLEAN_UP_OFF_HEAP:
// No-op
retValue = 1;
break;
default:
break;
}
return retValue;
}
LogicHE *makeLogicHEbasketball(ScummEngine_v100he *vm) {
return new LogicHEBasketball(vm);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,709 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/config-manager.h"
#include "common/savefile.h"
#include "scumm/he/intern_he.h"
#ifdef USE_ENET
#include "scumm/he/net/net_main.h"
#ifdef USE_BASIC_NET
#include "scumm/he/net/net_lobby.h"
#endif
#include "scumm/he/net/net_defines.h"
#endif
#include "scumm/he/logic_he.h"
// DirectPlay opcodes:
#define OP_NET_REMOTE_START_SCRIPT 1492
#define OP_NET_QUERY_PROVIDERS 1497
#define OP_NET_CLOSE_PROVIDER 1500
#define OP_NET_QUERY_SESSIONS 1501
#define OP_NET_GET_SESSION_NAME 1502
#define OP_NET_JOIN_SESSION 1504
#define OP_NET_END_SESSION 1505
#define OP_NET_ADD_USER 1506
#define OP_NET_WHO_SENT_THIS 1508
#define OP_NET_REMOTE_SEND_ARRAY 1509
#define OP_NET_INIT 1513
#define OP_NET_WHO_AM_I 1510
#define OP_NET_INIT_LAN_GAME 1515
#define OP_NET_SET_PROVIDER_BY_NAME 1516
// MAIA (Updater) opcodes.
#define OP_NET_CHECK_INTERNET_STATUS 3001
#define OP_NET_SHUT_DOWN_MAIA 3004
namespace Scumm {
/**
* Logic code for:
* Backyard Football
* Backyard Football 2002
*/
class LogicHEfootball : public LogicHE {
public:
LogicHEfootball(ScummEngine_v90he *vm) : LogicHE(vm) {}
int versionID() override;
int startOfFrame() override;
int32 dispatch(int op, int numArgs, int32 *args) override;
protected:
#ifdef USE_ENET
void netRemoteStartScript(int numArgs, int32 *args);
void netRemoteSendArray(int32 *args);
#endif
int lineEquation3D(int32 *args);
virtual int translateWorldToScreen(int32 *args);
int fieldGoalScreenTranslation(int32 *args);
virtual int translateScreenToWorld(int32 *args);
int nextPoint(int32 *args);
int computePlayerBallIntercepts(int32 *args);
int computeTwoCircleIntercepts(int32 *args);
};
int LogicHEfootball::versionID() {
return 1;
}
int LogicHEfootball::startOfFrame() {
#ifdef USE_ENET
#ifdef USE_BASIC_NET
// Football 2002 does not have lobby support, so
// _lobby is not defined.
if (_vm->_lobby)
_vm->_lobby->doNetworkOnceAFrame();
#endif
_vm->_net->doNetworkOnceAFrame(15);
#endif
return 0;
}
int32 LogicHEfootball::dispatch(int op, int numArgs, int32 *args) {
#if defined(USE_ENET) && defined(USE_BASIC_NET)
if (op > 2120 && op < 3003 && op != OP_NET_CHECK_INTERNET_STATUS &&
_vm->_lobby)
return _vm->_lobby->dispatch(op, numArgs, args);
#endif
int res = 0;
switch (op) {
case 1004:
res = lineEquation3D(args);
break;
case 1006:
res = translateWorldToScreen(args);
break;
case 1007:
res = fieldGoalScreenTranslation(args);
break;
case 1010:
res = translateScreenToWorld(args);
break;
case 1022:
res = nextPoint(args);
break;
case 1023:
res = computePlayerBallIntercepts(args);
break;
case 1024:
res = computeTwoCircleIntercepts(args);
break;
case 8221968:
// Someone had a fun and used his birthday as opcode number
res = getFromArray(args[0], args[1], args[2]);
break;
case OP_NET_INIT:
// Initialize network system, this gets called at boot up and
// sets VAR_NETWORK_AVAILABLE (100). We just return a 1 if
// ENet is compiled. Used in both 1999 and 2002.
#ifdef USE_ENET
res = 1;
#endif
break;
#ifdef USE_ENET
case OP_NET_REMOTE_START_SCRIPT:
netRemoteStartScript(numArgs, args);
break;
case OP_NET_CLOSE_PROVIDER:
res = _vm->_net->closeProvider();
break;
case OP_NET_QUERY_SESSIONS:
#ifdef USE_BASIC_NET
if (_vm->_lobby->_sessionId) {
_vm->_net->querySessions();
// Only proceed if we've found the session
// we're looking for.
res = _vm->_net->ifSessionExist(_vm->_lobby->_sessionId);
}
#endif
break;
case OP_NET_JOIN_SESSION:
#ifdef USE_BASIC_NET
if (_vm->_lobby->_sessionId) {
res = _vm->_net->joinSessionById(_vm->_lobby->_sessionId);
if (res) {
_vm->_net->stopQuerySessions();
}
}
#endif
break;
case OP_NET_END_SESSION:
res = _vm->_net->endSession();
break;
case OP_NET_ADD_USER:
char userName[MAX_PLAYER_NAME];
_vm->getStringFromArray(args[0], userName, sizeof(userName));
res = _vm->_net->addUser(userName, userName);
break;
case OP_NET_WHO_SENT_THIS:
res = _vm->_net->whoSentThis();
break;
case OP_NET_REMOTE_SEND_ARRAY:
netRemoteSendArray(args);
break;
case OP_NET_WHO_AM_I:
res = _vm->_net->whoAmI();
break;
#endif // USE_ENET
case OP_NET_CHECK_INTERNET_STATUS:
#if defined(USE_ENET) && defined(USE_BASIC_NET)
// We can only use the lobby system if both
// libcurl (for lobby communication) and
// ENet (for gameplay communication) is enabled.
// TODO: Actually check if we're connected to the
// Internet.
res = 1;
#endif
break;
case OP_NET_SHUT_DOWN_MAIA:
break;
case 1493: case 1494: case 1495: case 1496:
case 1498: case 1499:
case 1502: case 1503:
case 1507: case 1511:
case 1512: case 1514: case 1555:
// DirectPlay-related
// 1513: initialize
// 1555: set fake lag
break;
default:
LogicHE::dispatch(op, numArgs, args);
warning("Tell sev how to reproduce it (%d)", op);
}
return res;
}
int LogicHEfootball::lineEquation3D(int32 *args) {
// Identical to soccer's 1004 opcode
double res, a2, a4, a5;
a5 = ((double)args[4] - (double)args[1]) / ((double)args[5] - (double)args[2]);
a4 = ((double)args[3] - (double)args[0]) / ((double)args[5] - (double)args[2]);
a2 = (double)args[2] - (double)args[0] * a4 - args[1] * a5;
res = (double)args[6] * a4 + (double)args[7] * a5 + a2;
writeScummVar(108, (int32)res);
writeScummVar(109, (int32)a2);
writeScummVar(110, (int32)a5);
writeScummVar(111, (int32)a4);
return 1;
}
int LogicHEfootball::translateWorldToScreen(int32 *args) {
// This is more or less the inverse of translateScreenToWorld
const double a1 = args[1];
double res;
// 2.9411764e-4 = 1/3400
// 5.3050399e-2 = 1/18.85 = 20/377
// 1.1764706e-2 = 1/85 = 40/3400
// 1.2360656e-1 = 377/3050
res = (1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1 * args[0] +
a1 * 1.1764706e-2 + 46;
// Shortened / optimized version of that formula:
// res = (377.0 - a1 / 170.0) / 3050.0 * args[0] + a1 / 85.0 + 46;
writeScummVar(108, (int32)res);
// 1.2360656e-1 = 377/3050
// 1.1588235e-1 = 197/1700 = 394/3400
res = 640.0 - args[2] * 1.2360656e-1 - a1 * 1.1588235e-1 - 26;
writeScummVar(109, (int32)res);
return 1;
}
int LogicHEfootball::fieldGoalScreenTranslation(int32 *args) {
double res, temp;
temp = (double)args[1] * 0.32;
if (temp > 304.0)
res = -args[2] * 0.142;
else
res = args[2] * 0.142;
res += temp;
writeScummVar(108, (int32)res);
res = (1000.0 - args[2]) * 0.48;
writeScummVar(109, (int32)res);
return 1;
}
int LogicHEfootball::translateScreenToWorld(int32 *args) {
// This is more or less the inverse of translateWorldToScreen
double a1 = (640.0 - (double)args[1] - 26.0) / 1.1588235e-1;
// 2.9411764e-4 = 1/3400
// 5.3050399e-2 = 1/18.85 = 20/377
// 1.1764706e-2 = 1/85 = 40/3400
// 1.2360656e-1 = 377/3050
double a0 = ((double)args[0] - 46 - a1 * 1.1764706e-2) /
((1.0 - a1 * 2.9411764e-4 * 5.3050399e-2) * 1.2360656e-1);
writeScummVar(108, (int32)a0);
writeScummVar(109, (int32)a1);
return 1;
}
int LogicHEfootball::nextPoint(int32 *args) {
double res;
double var10 = args[4] - args[1];
double var8 = args[5] - args[2];
double var6 = args[3] - args[0];
res = sqrt(var8 * var8 + var6 * var6 + var10 * var10);
if (res >= (double)args[6]) {
var8 = (double)args[6] * var8 / res;
var10 = (double)args[6] * var10 / res;
var6 = (double)args[6] * var6 / res;
}
writeScummVar(108, (int32)var6);
writeScummVar(109, (int32)var10);
writeScummVar(110, (int32)var8);
return 1;
}
int LogicHEfootball::computePlayerBallIntercepts(int32 *args) {
double var10, var18, var20, var28, var30, var30_;
double argf[7];
for (int i = 0; i < 7; i++)
argf[i] = args[i];
var10 = (argf[3] - argf[1]) / (argf[2] - argf[0]);
var28 = var10 * var10 + 1;
var20 = argf[0] * var10;
var18 = (argf[5] + argf[1] + var20) * argf[4] * var10 * 2 +
argf[6] * argf[6] * var28 + argf[4] * argf[4] -
argf[0] * argf[0] * var10 * var10 -
argf[5] * argf[0] * var10 * 2 -
argf[5] * argf[1] * 2 -
argf[1] * argf[1] - argf[5] * argf[5];
if (var18 >= 0) {
var18 = sqrt(var18);
var30_ = argf[4] + argf[5] * var10 + argf[1] * var10 + argf[0] * var10 * var10;
var30 = (var30_ - var18) / var28;
var18 = (var30_ + var18) / var28;
if ((argf[0] - var30 < 0) && (argf[0] - var18 < 0)) {
var30_ = var30;
var30 = var18;
var18 = var30_;
}
var28 = var18 * var10 - var20 - argf[1];
var20 = var30 * var10 - var20 - argf[1];
} else {
var18 = 0;
var20 = 0;
var28 = 0;
var30 = 0;
}
writeScummVar(108, (int32)var18);
writeScummVar(109, (int32)var28);
writeScummVar(110, (int32)var30);
writeScummVar(111, (int32)var20);
return 1;
}
int LogicHEfootball::computeTwoCircleIntercepts(int32 *args) {
// Looks like this was just dummied out
writeScummVar(108, 0);
writeScummVar(109, 0);
writeScummVar(110, 0);
writeScummVar(111, 0);
return 1;
}
#ifdef USE_ENET
void LogicHEfootball::netRemoteStartScript(int numArgs, int32 *args) {
_vm->_net->remoteStartScript(args[0], args[1], args[2], numArgs - 3, &args[3]);
}
void LogicHEfootball::netRemoteSendArray(int32 *args) {
_vm->_net->remoteSendArray(args[0], args[1], args[2], args[3]);
}
#endif // USE_ENET
class LogicHEfootball2002 : public LogicHEfootball {
public:
LogicHEfootball2002(ScummEngine_v90he *vm) : LogicHEfootball(vm) {
_var0 = _var1 = _var2 = _var3 = _var4 = 0.0;
_angle = 0.0;
_maxX = -1;
_minX = 1000000;
}
int32 dispatch(int op, int numArgs, int32 *args) override;
private:
int translateWorldToScreen(int32 *args) override;
int translateScreenToWorld(int32 *args) override;
int getDayOfWeek();
int initScreenTranslations();
int getPlaybookFiles(int32 *args);
int largestFreeBlock();
#ifdef USE_ENET
int netGetSessionName(int index);
int netInitLanGame(int32 *args);
#endif
float _var0;
float _var1;
float _var2;
float _var3;
float _var4;
float _angle;
int32 _maxX;
int32 _minX;
#ifdef USE_ENET
int _requestedSessionIndex = -2;
#endif
};
int32 LogicHEfootball2002::dispatch(int op, int numArgs, int32 *args) {
int32 res = 0;
switch (op) {
case 1025:
res = getDayOfWeek();
break;
case 1026:
res = initScreenTranslations();
break;
case 1027:
res = getPlaybookFiles(args);
break;
case 1028:
res = largestFreeBlock();
break;
case 1029:
// Clean-up off heap
// Dummied in the Windows U32
res = 1;
break;
case 1030:
// Get Computer Name (online play only)
if (ConfMan.hasKey("network_player_name")) {
res = _vm->setupStringArrayFromString(ConfMan.get("network_player_name").c_str());
}
break;
// These cases are outside #ifdef USE_ENET intentionally
// to silence warnings:
case OP_NET_QUERY_PROVIDERS:
#ifdef USE_ENET
res = _vm->_net->queryProviders();
#endif
break;
case OP_NET_SET_PROVIDER_BY_NAME:
#ifdef USE_ENET
res = _vm->_net->setProviderByName(args[0], args[1]);
if (res)
_requestedSessionIndex = _vm->networkSessionDialog();
if (_requestedSessionIndex == -2) {
// Cancelled out the join dialog.
_vm->_net->closeProvider();
res = 0;
}
#endif
break;
#ifdef USE_ENET
case OP_NET_QUERY_SESSIONS:
if (_requestedSessionIndex > -1)
// Emulate that we've found a session.
res = 1;
break;
case OP_NET_GET_SESSION_NAME:
res = netGetSessionName(args[0]);
break;
case OP_NET_INIT_LAN_GAME:
res = netInitLanGame(args);
break;
#endif
default:
res = LogicHEfootball::dispatch(op, numArgs, args);
break;
}
return res;
}
int LogicHEfootball2002::translateWorldToScreen(int32 *args) {
// While this performs the same task as football's 1006 opcode,
// the implementation is different. Note that this is also the
// same as basketball's 1006 opcode with different constants!
double v9;
if (args[1] >= _minX) {
if (args[1] < _maxX) {
v9 = (sqrt(_var1 + args[1]) - sqrt(_var1)) / sqrt(_var0);
} else {
double v10 = sqrt(_var0 * (_maxX + _var1));
v9 = 1.0 / (v10 + v10) * (args[1] - _maxX) + 451.0;
}
} else {
double v8 = sqrt(_var0 * (_minX + _var1));
v9 = 1.0 / (v8 + v8) * (args[1] - _minX) - 29.0;
}
double v11 = tan(_angle);
double v12, v13;
if (v9 >= -29.0) {
if (v9 >= 451.0) {
v12 = 1517.0 - (451.0 / v11 + 451.0 / v11);
v13 = tan(1.570796326794895 - _angle) * 451.0;
} else {
v12 = 1517.0 - (v9 / v11 + v9 / v11);
v13 = tan(1.570796326794895 - _angle) * v9;
}
} else {
v12 = 1517.0 - (-29.0 / v11 + -29.0 / v11);
v13 = tan(1.570796326794895 - _angle) * -29.0;
}
writeScummVar(108, scummRound(v12 * args[0] / 12200.0 + v13 + 41.0));
writeScummVar(109, scummRound(611.0 - v9 - v12 * args[2] / 12200.0));
return 1;
}
int LogicHEfootball2002::translateScreenToWorld(int32 *args) {
// While this performs the same task as football's 1010 opcode,
// the implementation is different. Note that this is also the
// same as basketball's 1010 opcode with different constants!
double v15 = 611.0 - args[1];
double v5 = tan(_angle);
double v4, v6, v7;
if (v15 >= -29.0) {
if (v15 >= 451.0) {
v4 = (_var2 * 902.0 + _var3) * (v15 - 451.0) + _maxX;
v6 = 1517.0 - (451.0 / v5 + 451.0 / v5);
v7 = tan(1.570796326794895 - _angle) * 451.0;
} else {
v4 = (v15 * _var2 + _var3) * v15 + _var4;
v6 = 1517.0 - (v15 / v5 + v15 / v5);
v7 = tan(1.570796326794895 - _angle) * v15;
}
} else {
v4 = (_var3 - _var2 * 58.0) * (v15 - -29.0) + _minX;
v6 = 1517.0 - (-29.0 / v5 + -29.0 / v5);
v7 = tan(1.570796326794895 - _angle) * -29.0;
}
writeScummVar(108, scummRound((args[0] - (v7 + 41.0)) * (12200.0 / v6)));
writeScummVar(109, scummRound(v4));
return 1;
}
int LogicHEfootball2002::getDayOfWeek() {
// Get day of week, store in var 108
TimeDate time;
_vm->_system->getTimeAndDate(time);
writeScummVar(108, time.tm_wday);
return 1;
}
int LogicHEfootball2002::initScreenTranslations() {
// Set values used by translateWorldToScreen/translateScreenToWorld
_var0 = _var2 = 0.0029172597f;
_var1 = 4896.3755f;
_var3 = 7.5588355f;
_var4 = 0.0f;
_angle = (float)atan(2.899280575539569);
_maxX = 4002;
_minX = -217;
return 1;
}
int LogicHEfootball2002::getPlaybookFiles(int32 *args) {
// Get the pattern and then skip over the directory prefix ("*\" or "*:")
// Also prepend the target name
Common::String targetName = _vm->getTargetName();
Common::String basePattern = ((const char *)_vm->getStringAddress(args[0] & ~MAGIC_ARRAY_NUMBER) + 2);
Common::String pattern = targetName + '-' + basePattern;
// Prepare a buffer to hold the file names
Common::String output;
// Get the list of file names that match the pattern and iterate over it
Common::StringArray fileList = _vm->getSaveFileManager()->listSavefiles(pattern);
for (uint32 i = 0; i < fileList.size(); i++) {
// Isolate the base part of the filename and concatenate it to our buffer
Common::String fileName(fileList[i].c_str() + targetName.size() + 1, fileList[i].size() - (basePattern.size() - 1) - (targetName.size() + 1));
output += fileName + '>'; // names separated by '>'
}
// Now store the result in an array
int array = _vm->setupStringArray(output.size());
Common::strlcpy((char *)_vm->getStringAddress(array), output.c_str(), output.size() + 1);
// And store the array index in variable 108
writeScummVar(108, array);
return 1;
}
int LogicHEfootball2002::largestFreeBlock() {
// The Windows version always sets the variable to this
// The Mac version actually checks for the largest free block
writeScummVar(108, 100000000);
return 1;
}
#ifdef USE_ENET
int LogicHEfootball2002::netGetSessionName(int index) {
char name[MAX_SESSION_NAME];
_vm->_net->getSessionName(_requestedSessionIndex, name, sizeof(name));
return _vm->setupStringArrayFromString(name);
}
int LogicHEfootball2002::netInitLanGame(int32 *args) {
// Initialize Session
// Arg 0 is the provider name ("TCP/IP")
// Arg 1 is the session name
// Arg 2 is the host name.
// Arg 3 is a boolean determining we're hosting or joining a session.
char sessionName[MAX_SESSION_NAME];
_vm->getStringFromArray(args[1], sessionName, sizeof(sessionName));
char userName[MAX_PLAYER_NAME];
_vm->getStringFromArray(args[2], userName, sizeof(userName));
int res;
if (args[3] == 1) {
// Stop querying sessions if we haven't already
_vm->_net->stopQuerySessions();
// And host our new game.
// If there's a custom game name, use that instead.
if (ConfMan.hasKey("game_session_name")) {
Common::String gameSessionName = ConfMan.get("game_session_name");
return _vm->_net->hostGame(const_cast<char *>(gameSessionName.c_str()), userName);
}
res = _vm->_net->hostGame(sessionName, userName);
} else {
res = _vm->_net->joinSession(_requestedSessionIndex);
if (res)
_vm->_net->addUser(userName, userName);
_vm->_net->stopQuerySessions();
}
return res;
}
#endif
LogicHE *makeLogicHEfootball(ScummEngine_v90he *vm) {
return new LogicHEfootball(vm);
}
LogicHE *makeLogicHEfootball2002(ScummEngine_v90he *vm) {
return new LogicHEfootball2002(vm);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,215 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
namespace Scumm {
/**
* Logic code for:
* Freddi Fish's One-Stop Fun Shop
* Pajama Sam's One-Stop Fun Shop
* Putt-Putt's One-Stop Fun Shop
*/
class LogicHEfunshop : public LogicHE {
public:
LogicHEfunshop(ScummEngine_v90he *vm) : LogicHE(vm) {}
int versionID() override;
int32 dispatch(int op, int numArgs, int32 *args) override;
private:
void op_1004(int32 *args);
void op_1005(int32 *args);
int checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y);
};
int LogicHEfunshop::versionID() {
return 1;
}
int32 LogicHEfunshop::dispatch(int op, int numArgs, int32 *args) {
switch (op) {
case 1004:
op_1004(args);
break;
case 1005:
op_1005(args);
break;
default:
break;
}
return 0;
}
void LogicHEfunshop::op_1004(int32 *args) {
double data[8], at, sq;
int32 x, y;
int i;
for (i = 0; i <= 6; i += 2) {
data[i] = getFromArray(args[0], 0, 519 + i);
data[i + 1] = getFromArray(args[0], 0, 519 + i + 1);
}
int s = checkShape((int32)data[0], (int32)data[1], (int32)data[4], (int32)data[5],
(int32)data[2], (int32)data[3], (int32)data[6], (int32)data[7], &x, &y);
if (s != 1) {
error("LogicHEfunshop::op_1004: Your shape has defied the laws of physics");
return;
}
for (i = 0; i <= 6; i += 2) {
data[i] -= (double)x;
data[i + 1] -= (double)y;
}
double a1 = (double)args[1] * DEG2RAD;
for (i = 0; i <= 6; i += 2) {
at = atan2(data[i + 1], data[i]);
sq = sqrt(data[i + 1] * data[i + 1] + data[i] * data[i]);
if (at <= 0)
at += 2 * M_PI;
data[i] = cos(at + a1) * sq;
data[i + 1] = sin(at + a1) * sq;
}
double minx = data[0];
double miny = data[1];
for (i = 0; i <= 6; i += 2) {
if (data[i] < minx)
minx = data[i];
if (data[i + 1] < miny)
miny = data[i + 1];
}
for (i = 0; i <= 6; i += 2) {
data[i] -= minx;
data[i + 1] -= miny;
putInArray(args[0], 0, 519 + i, scummRound(data[i]));
putInArray(args[0], 0, 519 + i + 1, scummRound(data[i + 1]));
}
}
void LogicHEfunshop::op_1005(int32 *args) {
double data[8];
double args1, args2;
int i;
for (i = 520; i <= 526; i += 2) {
data[i - 520] = getFromArray(args[0], 0, i - 1);
data[i - 520 + 1] = getFromArray(args[0], 0, i);
}
args1 = (double)args[1] * 0.01 + 1;
args2 = (double)args[2] * 0.01 + 1;
for (i = 0; i < 4; i++) {
data[2 * i] *= args1;
data[2 * i + 1] *= args2;
}
for (i = 520; i <= 526; i += 2) {
putInArray(args[0], 0, i - 1, scummRound(data[i - 520]));
putInArray(args[0], 0, i, scummRound(data[i - 520 + 1]));
}
}
int LogicHEfunshop::checkShape(int32 data0, int32 data1, int32 data4, int32 data5, int32 data2, int32 data3, int32 data6, int32 data7, int32 *x, int32 *y) {
int32 diff5_1, diff0_4, diff7_3, diff2_6;
int32 diff1, diff2;
int32 delta, delta2;
int32 sum1, sum2;
diff0_4 = data0 - data4;
diff5_1 = data5 - data1;
diff1 = data1 * data4 - data0 * data5;
sum1 = diff0_4 * data3 + diff1 + diff5_1 * data2;
sum2 = diff0_4 * data7 + diff1 + diff5_1 * data6;
if (sum1 != 0 && sum2 != 0) {
sum2 ^= sum1;
if (sum2 >= 0)
return 0;
}
diff2_6 = data2 - data6;
diff7_3 = data7 - data3;
diff2 = data3 * data6 - data2 * data7;
sum1 = diff2_6 * data1 + diff2 + diff7_3 * data0;
sum2 = diff2_6 * data5 + diff2 + diff7_3 * data4;
if (sum1 != 0 && sum2 != 0) {
sum2 ^= sum1;
if (sum2 >= 0)
return 0;
}
delta = diff2_6 * diff5_1 - diff0_4 * diff7_3;
if (delta == 0) {
return 2;
}
if (delta < 0) {
data7 = -((delta + 1) >> 1);
} else {
data7 = delta >> 1;
}
delta2 = diff2 * diff0_4 - diff1 * diff2_6;
if (delta2 < 0) {
delta2 -= data7;
} else {
delta2 += data7;
}
*x = delta2 / delta;
delta2 = diff1 * diff7_3 - diff2 * diff5_1;
if (delta2 < 0) {
delta2 -= data7;
} else {
delta2 += data7;
}
*y = delta2 / delta;
return 1;
}
LogicHE *makeLogicHEfunshop(ScummEngine_v90he *vm) {
return new LogicHEfunshop(vm);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,784 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
#include "scumm/he/moonbase/moonbase.h"
#include "scumm/he/moonbase/ai_main.h"
#ifdef USE_ENET
#include "scumm/he/net/net_main.h"
#include "scumm/he/net/net_defines.h"
#endif
namespace Scumm {
/**
* Logic code for:
* Moonbase Commander
*/
class LogicHEmoonbase : public LogicHE {
public:
LogicHEmoonbase(ScummEngine_v100he *vm) : LogicHE(vm) { _vm1 = vm; }
int versionID() override;
int startOfFrame() override;
int32 dispatch(int op, int numArgs, int32 *args) override;
bool userCodeProcessWizImageCmd(const WizImageCommand *icmdPtr) override;
bool overrideImageHitTest(int *outValue, int globNum, int state, int x, int y, int32 flags) override;
bool overrideImagePixelHitTest(int *outValue, int globNum, int state, int x, int y, int32 flags) override;
private:
int op_create_multi_state_wiz(int op, int numArgs, int32 *args);
int op_load_multi_channel_wiz(int op, int numArgs, int32 *args);
int op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args);
void op_dos_command(int op, int numArgs, int32 *args);
void op_set_fow_sentinel(int32 *args);
void op_set_fow_information(int op, int numArgs, int32 *args);
int op_set_fow_image(int op, int numArgs, int32 *args);
void op_ai_test_kludge(int op, int numArgs, int32 *args);
int op_ai_master_control_program(int op, int numArgs, int32 *args);
void op_ai_reset(int op, int numArgs, int32 *args);
void op_ai_set_type(int op, int numArgs, int32 *args);
void op_ai_clean_up(int op, int numArgs, int32 *args);
#ifdef USE_ENET
void op_net_remote_start_script(int op, int numArgs, int32 *args);
void op_net_remote_send_array(int op, int numArgs, int32 *args);
int op_net_remote_start_function(int op, int numArgs, int32 *args);
int op_net_do_init_all(int op, int numArgs, int32 *args);
int op_net_do_init_provider(int op, int numArgs, int32 *args);
int op_net_do_init_session(int op, int numArgs, int32 *args);
int op_net_do_init_user(int op, int numArgs, int32 *args);
int op_net_query_providers(int op, int numArgs, int32 *args);
int op_net_get_provider_name(int op, int numArgs, int32 *args);
int op_net_set_provider(int op, int numArgs, int32 *args);
int op_net_close_provider(int op, int numArgs, int32 *args);
int op_net_start_query_sessions(int op, int numArgs, int32 *args);
int op_net_update_query_sessions(int op, int numArgs, int32 *args);
int op_net_stop_query_sessions(int op, int numArgs, int32 *args);
int op_net_query_sessions(int op, int numArgs, int32 *args);
int op_net_get_session_name(int op, int numArgs, int32 *args);
int op_net_get_session_player_count(int op, int numArgs, int32 *args);
int op_net_destroy_player(int op, int numArgs, int32 *args);
int op_net_get_player_long_name(int op, int numArgs, int32 *args);
int op_net_get_player_short_name(int op, int numArgs, int32 *args);
int op_net_create_session(int op, int numArgs, int32 *args);
int op_net_join_session(int op, int numArgs, int32 *args);
int op_net_end_session(int op, int numArgs, int32 *args);
int op_net_disable_session_player_join(int op, int numArgs, int32 *args);
int op_net_enable_session_player_join(int op, int numArgs, int32 *args);
int op_net_set_ai_player_count(int op, int numArgs, int32 *args);
int op_net_add_user(int op, int numArgs, int32 *args);
int op_net_remove_user(int op, int numArgs, int32 *args);
int op_net_who_sent_this(int op, int numArgs, int32 *args);
int op_net_who_am_i(int op, int numArgs, int32 *args);
int op_net_set_provider_by_name(int op, int numArgs, int32 *args);
void op_net_set_fake_latency(int op, int numArgs, int32 *args);
int op_net_get_host_name(int op, int numArgs, int32 *args);
int op_net_get_ip_from_name(int op, int numArgs, int32 *args);
int op_net_host_tcpip_game(int op, int numArgs, int32 *args);
int op_net_join_tcpip_game(int op, int numArgs, int32 *args);
#endif
private:
ScummEngine_v100he *_vm1;
};
int LogicHEmoonbase::versionID() {
if (_vm->_game.features & GF_DEMO)
return -100;
else if (strcmp(_vm->_game.variant, "1.1") == 0)
return 110;
else
return 100;
}
#define OP_CREATE_MULTI_STATE_WIZ 100
#define OP_LOAD_MULTI_CHANNEL_WIZ 101
#define OP_WIZ_FROM_MULTI_CHANNEL_WIZ 102
#define OP_DOS_COMMAND 103
#define OP_SET_FOW_SENTINEL 104
#define OP_SET_FOW_INFORMATION 105
#define OP_SET_FOW_IMAGE 106
#define OP_AI_TEST_KLUDGE 10000
#define OP_AI_MASTER_CONTROL_PROGRAM 10001
#define OP_AI_RESET 10002
#define OP_AI_SET_TYPE 10003
#define OP_AI_CLEAN_UP 10004
#define OP_NET_REMOTE_START_SCRIPT 1492
#define OP_NET_DO_INIT_ALL 1493
#define OP_NET_DO_INIT_PROVIDER 1494
#define OP_NET_DO_INIT_SESSION 1495
#define OP_NET_DO_INIT_USER 1496
#define OP_NET_QUERY_PROVIDERS 1497
#define OP_NET_GET_PROVIDER_NAME 1498
#define OP_NET_SET_PROVIDER 1499
#define OP_NET_CLOSE_PROVIDER 1500
#define OP_NET_QUERY_SESSIONS 1501
#define OP_NET_GET_SESSION_NAME 1502
#define OP_NET_CREATE_SESSION 1503
#define OP_NET_JOIN_SESSION 1504
#define OP_NET_END_SESSION 1505
#define OP_NET_ADD_USER 1506
#define OP_NET_REMOVE_USER 1507
#define OP_NET_WHO_SENT_THIS 1508
#define OP_NET_REMOTE_SEND_ARRAY 1509
#define OP_NET_WHO_AM_I 1510
#define OP_NET_REMOTE_START_FUNCTION 1511
#define OP_NET_GET_PLAYER_LONG_NAME 1512
#define OP_NET_GET_PLAYER_SHORT_NAME 1513
#define OP_NET_SET_PROVIDER_BY_NAME 1516
#define OP_NET_HOST_TCPIP_GAME 1517
#define OP_NET_JOIN_TCPIP_GAME 1518
#define OP_NET_SET_FAKE_LAG 1555
#define OP_NET_SET_FAKE_LATENCY 1555 /* SET_FAKE_LAG is a valid alias for backwards compatibility */
#define OP_NET_GET_HOST_NAME 1556
#define OP_NET_GET_IP_FROM_NAME 1557
#define OP_NET_GET_SESSION_PLAYER_COUNT 1558
#define OP_NET_DISABLE_SESSION_PLAYER_JOIN 1559
#define OP_NET_START_QUERY_SESSIONS 1560
#define OP_NET_UPDATE_QUERY_SESSIONS 1561
#define OP_NET_STOP_QUERY_SESSIONS 1562
#define OP_NET_DESTROY_PLAYER 1563
#define OP_NET_ENABLE_SESSION_PLAYER_JOIN 1564
#define OP_NET_SET_AI_PLAYER_COUNT 1565
int LogicHEmoonbase::startOfFrame() {
#ifdef USE_ENET
_vm1->_net->doNetworkOnceAFrame(15); // Value should be passed in...
#endif
return 0;
}
int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) {
switch (op) {
// Development kludge commands which are called within a room
// which is not compiled into the final game files
case OP_CREATE_MULTI_STATE_WIZ:
return op_create_multi_state_wiz(op, numArgs, args);
case OP_LOAD_MULTI_CHANNEL_WIZ:
return op_load_multi_channel_wiz(op, numArgs, args);
case OP_WIZ_FROM_MULTI_CHANNEL_WIZ:
return op_wiz_from_multi_channel_wiz(op, numArgs, args);
case OP_DOS_COMMAND:
op_dos_command(op, numArgs, args);
break;
// "Fog of war" commands
case OP_SET_FOW_SENTINEL:
op_set_fow_sentinel(args);
break;
case OP_SET_FOW_INFORMATION:
op_set_fow_information(op, numArgs, args);
break;
case OP_SET_FOW_IMAGE:
return op_set_fow_image(op, numArgs, args);
// AI commands
case OP_AI_TEST_KLUDGE:
op_ai_test_kludge(op, numArgs, args);
break;
case OP_AI_MASTER_CONTROL_PROGRAM:
return op_ai_master_control_program(op, numArgs, args);
case OP_AI_RESET:
op_ai_reset(op, numArgs, args);
break;
case OP_AI_SET_TYPE:
op_ai_set_type(op, numArgs, args);
break;
case OP_AI_CLEAN_UP:
op_ai_clean_up(op, numArgs, args);
break;
#ifdef USE_ENET
// Network commands
case OP_NET_REMOTE_START_SCRIPT:
op_net_remote_start_script(op, numArgs, args);
break;
case OP_NET_REMOTE_SEND_ARRAY:
op_net_remote_send_array(op, numArgs, args);
break;
case OP_NET_REMOTE_START_FUNCTION:
return op_net_remote_start_function(op, numArgs, args);
case OP_NET_DO_INIT_ALL:
return op_net_do_init_all(op, numArgs, args);
case OP_NET_DO_INIT_PROVIDER:
return op_net_do_init_provider(op, numArgs, args);
case OP_NET_DO_INIT_SESSION:
return op_net_do_init_session(op, numArgs, args);
case OP_NET_DO_INIT_USER:
return op_net_do_init_user(op, numArgs, args);
case OP_NET_QUERY_PROVIDERS:
return op_net_query_providers(op, numArgs, args);
case OP_NET_GET_PROVIDER_NAME:
return op_net_get_provider_name(op, numArgs, args);
case OP_NET_SET_PROVIDER:
return op_net_set_provider(op, numArgs, args);
case OP_NET_CLOSE_PROVIDER:
return op_net_close_provider(op, numArgs, args);
case OP_NET_START_QUERY_SESSIONS:
return op_net_start_query_sessions(op, numArgs, args);
case OP_NET_UPDATE_QUERY_SESSIONS:
return op_net_update_query_sessions(op, numArgs, args);
case OP_NET_STOP_QUERY_SESSIONS:
return op_net_stop_query_sessions(op, numArgs, args);
case OP_NET_QUERY_SESSIONS:
return op_net_query_sessions(op, numArgs, args);
case OP_NET_GET_SESSION_NAME:
return op_net_get_session_name(op, numArgs, args);
case OP_NET_GET_SESSION_PLAYER_COUNT:
return op_net_get_session_player_count(op, numArgs, args);
case OP_NET_DESTROY_PLAYER:
return op_net_destroy_player(op, numArgs, args);
case OP_NET_GET_PLAYER_LONG_NAME:
return op_net_get_player_long_name(op, numArgs, args);
case OP_NET_GET_PLAYER_SHORT_NAME:
return op_net_get_player_short_name(op, numArgs, args);
case OP_NET_CREATE_SESSION:
return op_net_create_session(op, numArgs, args);
case OP_NET_JOIN_SESSION:
return op_net_join_session(op, numArgs, args);
case OP_NET_END_SESSION:
return op_net_end_session(op, numArgs, args);
case OP_NET_DISABLE_SESSION_PLAYER_JOIN:
return op_net_disable_session_player_join(op, numArgs, args);
case OP_NET_ENABLE_SESSION_PLAYER_JOIN:
return op_net_enable_session_player_join(op, numArgs, args);
case OP_NET_SET_AI_PLAYER_COUNT:
return op_net_set_ai_player_count(op, numArgs, args);
case OP_NET_ADD_USER:
return op_net_add_user(op, numArgs, args);
case OP_NET_REMOVE_USER:
return op_net_remove_user(op, numArgs, args);
case OP_NET_WHO_SENT_THIS:
return op_net_who_sent_this(op, numArgs, args);
case OP_NET_WHO_AM_I:
return op_net_who_am_i(op, numArgs, args);
case OP_NET_SET_PROVIDER_BY_NAME:
return op_net_set_provider_by_name(op, numArgs, args);
case OP_NET_SET_FAKE_LATENCY: // SET_FAKE_LAG is a valid alias for backwards compatibility
op_net_set_fake_latency(op, numArgs, args);
break;
case OP_NET_GET_HOST_NAME:
return op_net_get_host_name(op, numArgs, args);
case OP_NET_GET_IP_FROM_NAME:
return op_net_get_ip_from_name(op, numArgs, args);
case OP_NET_HOST_TCPIP_GAME:
return op_net_host_tcpip_game(op, numArgs, args);
case OP_NET_JOIN_TCPIP_GAME:
return op_net_join_tcpip_game(op, numArgs, args);
#endif
default:
LogicHE::dispatch(op, numArgs, args);
}
return 0;
}
bool LogicHEmoonbase::userCodeProcessWizImageCmd(const WizImageCommand *params) {
// Make sure there is a imgcmd struct and it's a render operation
if (!params) {
return false;
}
if (params->actionType != kWADraw) {
return false;
}
// If there are special rendering bits bail
if (params->flags & kWRFSpecialRenderBitMask) {
return false;
}
// Check to see if the caller wants to use a source buffer
int sourceBufferImage = 0;
if (params->actionFlags & kWAFSourceImage) {
sourceBufferImage = params->sourceImage;
}
// Check to see if the caller wants to render into another image.
int destImage = 0;
if (params->actionFlags & kWAFDestImage) {
destImage = params->destImageNumber;
}
// Get the glob address and state number
byte *globPtr = _vm->getResourceAddress(rtImage, params->image);
if (!globPtr) {
error("LogicHEmoonbase::userCodeProcessWizImageCmd(): Image %d not on heap?", params->image);
return false;
}
int state = (params->actionFlags & kWAFState) ? params->state : 0;
// Make sure the dest buffer is one we can handle (Background or foreground)
WizMultiTypeBitmap mappedMultiBM;
bool drawIntoBackground = ((params->flags & kWRFBackground) == kWRFBackground);
if (destImage) {
if (!_vm->_wiz->dwGetMultiTypeBitmapFromImageState(destImage, 0, &mappedMultiBM)) {
return false;
}
} else {
if (!_vm->_wiz->pgGetMultiTypeBitmapFromDrawBuffer(&mappedMultiBM, drawIntoBackground)) {
return false;
}
}
Common::Rect clipRect, bitmapLimitsRect;
bitmapLimitsRect.left = 0;
bitmapLimitsRect.top = 0;
bitmapLimitsRect.right = (mappedMultiBM.width - 1);
bitmapLimitsRect.bottom = (mappedMultiBM.height - 1);
if (params->actionFlags & kWAFRect) {
clipRect.left = params->box.left;
clipRect.top = params->box.top;
clipRect.right = params->box.right;
clipRect.bottom = params->box.bottom;
if (!_vm->_wiz->findRectOverlap(&clipRect, &bitmapLimitsRect)) {
return true;
}
} else {
clipRect = bitmapLimitsRect;
}
// Validate source image if requested
byte *altSourceData = nullptr;
if (sourceBufferImage) {
WizMultiTypeBitmap sourceMultiBM;
if (!_vm->_wiz->dwGetMultiTypeBitmapFromImageState(sourceBufferImage, 0, &sourceMultiBM)) {
return false;
}
if ((sourceMultiBM.width != mappedMultiBM.width) ||
(sourceMultiBM.height != mappedMultiBM.height) ||
(sourceMultiBM.stride != mappedMultiBM.stride) ||
(sourceMultiBM.format != mappedMultiBM.format) ||
(sourceMultiBM.bpp != mappedMultiBM.bpp)) {
return false;
}
altSourceData = sourceMultiBM.data;
}
// Convert the icmd struct to useful info for the renderer
int32 locationX, locationY;
if (params->actionFlags & kWAFSpot) {
locationX = params->xPos;
locationY = params->yPos;
} else {
locationX = 0;
locationY = 0;
}
int32 wizDrawFlags;
if (params->actionFlags & kWAFFlags) {
wizDrawFlags = params->flags;
} else {
wizDrawFlags = 0;
}
// Get any palette specified
byte *paletteData;
if (params->actionFlags & kWAFPalette) {
paletteData = _vm->getHEPaletteSlot(params->palette);
} else {
paletteData = _vm->getHEPaletteSlot(1);
}
// Finally call the renderer (returns false if not handled or error)
if ((_vm1->_moonbase->_fowSentinelImage != params->image) ||
(_vm1->_moonbase->_fowSentinelState != state) ||
(_vm1->_moonbase->_fowSentinelConditionBits != (uint32)params->extendedRenderInfo.conditionBits)) {
if (!_vm->_wiz->drawMoonbaseLayeredWiz(
mappedMultiBM.data,
mappedMultiBM.width, mappedMultiBM.height,
mappedMultiBM.stride, mappedMultiBM.format, mappedMultiBM.bpp,
globPtr, locationX, locationY, state,
clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
wizDrawFlags, params->extendedRenderInfo.conditionBits,
paletteData, altSourceData)) {
return false;
}
} else {
_vm1->_moonbase->renderFOW(&mappedMultiBM);
}
if (destImage) {
_vm->_res->setModified(rtImage, destImage);
} else {
Common::Rect updateRectangle = clipRect;
if (drawIntoBackground) {
_vm->backgroundToForegroundBlit(updateRectangle);
} else {
_vm->markRectAsDirty(kMainVirtScreen, updateRectangle);
}
}
return true;
}
bool LogicHEmoonbase::overrideImageHitTest(int *outValue, int globNum, int state, int x, int y, int32 flags) {
// Make sure this is a hit-test operation is a type we can handle
byte *globPtr = _vm->getResourceAddress(rtImage, globNum);
if (!globPtr) {
warning("LogicHEmoonbase::overrideImageHitTest(): Image %d not on heap", globNum);
return false;
}
int32 actualValue = 0;
int32 eatValue = 0;
if (!_vm->_wiz->moonbaseLayeredWizHitTest(&eatValue, &actualValue, globPtr, state, x, y, flags, (uint32)0)) {
return false;
}
*outValue = (int)eatValue;
return true;
}
bool LogicHEmoonbase::overrideImagePixelHitTest(int *outValue, int globNum, int state, int x, int y, int32 flags) {
// Make sure this is a hit-test operation is a type we can handle
byte *globPtr = _vm->getResourceAddress(rtImage, globNum);
if (!globPtr) {
warning("LogicHEmoonbase::overrideImagePixelHitTest(): Image %d not on heap", globNum);
return false;
}
int32 actualValue = ~0;
int32 eatValue = 0;
if (!_vm->_wiz->moonbaseLayeredWizHitTest(&eatValue, &actualValue, globPtr, state, x, y, flags, (uint32)0)) {
return false;
}
*outValue = (int)actualValue;
return true;
}
int LogicHEmoonbase::op_create_multi_state_wiz(int op, int numArgs, int32 *params) {
debug("LogicHEmoonbase::op_create_multi_state_wiz(): Unused development command called by a script non compiled in the final game files, ignoring");
LogicHE::dispatch(op, numArgs, params);
return 1;
}
int LogicHEmoonbase::op_load_multi_channel_wiz(int op, int numArgs, int32 *params) {
debug("LogicHEmoonbase::op_load_multi_channel_wiz(): Unused development command called by a script non compiled in the final game files, ignoring");
LogicHE::dispatch(op, numArgs, params);
return 1;
}
int LogicHEmoonbase::op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *params) {
debug("LogicHEmoonbase::op_wiz_from_multi_channel_wiz(): Unused development command called by a script non compiled in the final game files, ignoring");
LogicHE::dispatch(op, numArgs, params);
return 1;
}
void LogicHEmoonbase::op_dos_command(int op, int numArgs, int32 *params) {
debug("LogicHEmoonbase::op_dos_command(): Unused development command called by a script non compiled in the final game files, ignoring");
LogicHE::dispatch(op, numArgs, params);
}
void LogicHEmoonbase::op_set_fow_sentinel(int32 *args) {
debug(2, "op_set_fow_sentinel(%d, %d, %d)", args[0], args[1], args[2]);
_vm1->_moonbase->_fowSentinelImage = args[0];
_vm1->_moonbase->_fowSentinelState = args[1];
_vm1->_moonbase->_fowSentinelConditionBits = args[2];
}
void LogicHEmoonbase::op_set_fow_information(int op, int numArgs, int32 *args) {
Common::String str;
str = Common::String::format("op_set_fow_information(%d", args[0]);
for (int i = 1; i < numArgs; i++) {
str += Common::String::format(", %d", args[i]);
}
str += ")";
debug(2, "%s", str.c_str());
_vm1->_moonbase->setFOWInfo(
args[0], // array
args[1], // array down dimension
args[2], // array across dimension
args[3], // logical view X coordinate
args[4], // logical view Y coordinate
args[5], // screen draw clip rect x1
args[6], // screen draw clip rect y1
args[7], // screen draw clip rect x2
args[8], // screen draw clip rect y2
args[9], // techinque
args[10] // frame
);
}
int LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) {
debug(2, "op_set_fow_image(%d)", args[0]);
return _vm1->_moonbase->setFOWImage(args[0]) ? 1 : 0;
}
void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) {
warning("STUB: op_ai_test_kludge()");
LogicHE::dispatch(op, numArgs, args);
}
int LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) {
debugC(DEBUG_MOONBASE_AI, "op_ai_master_control_program()");
return _vm1->_moonbase->_ai->masterControlProgram(numArgs, args);
}
void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) {
debugC(DEBUG_MOONBASE_AI, "op_ai_reset())");
_vm1->_moonbase->_ai->resetAI();
}
void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) {
debugC(DEBUG_MOONBASE_AI, "op_ai_set_type()");
_vm1->_moonbase->_ai->setAIType(numArgs, args);
}
void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) {
debugC(DEBUG_MOONBASE_AI, "op_ai_clean_up()");
_vm1->_moonbase->_ai->cleanUpAI();
}
#ifdef USE_ENET
void LogicHEmoonbase::op_net_remote_start_script(int op, int numArgs, int32 *args) {
_vm1->_net->remoteStartScript(args[0], args[1], args[2], numArgs - 3, &args[3]);
}
void LogicHEmoonbase::op_net_remote_send_array(int op, int numArgs, int32 *args) {
_vm1->_net->remoteSendArray(args[0], args[1], args[2], args[3]);
}
int LogicHEmoonbase::op_net_remote_start_function(int op, int numArgs, int32 *args) {
return _vm1->_net->remoteStartScriptFunction(args[0], args[1], args[2], args[3], numArgs - 4, &args[4]);
}
int LogicHEmoonbase::op_net_do_init_all(int op, int numArgs, int32 *args) {
return _vm1->_net->initAll();
}
int LogicHEmoonbase::op_net_do_init_provider(int op, int numArgs, int32 *args) {
return _vm1->_net->initProvider();
}
int LogicHEmoonbase::op_net_do_init_session(int op, int numArgs, int32 *args) {
return _vm1->_net->initSession();
}
int LogicHEmoonbase::op_net_do_init_user(int op, int numArgs, int32 *args) {
return _vm1->_net->initUser();
}
int LogicHEmoonbase::op_net_query_providers(int op, int numArgs, int32 *args) {
return _vm1->_net->queryProviders();
}
int LogicHEmoonbase::op_net_get_provider_name(int op, int numArgs, int32 *args) {
char name[MAX_PROVIDER_NAME];
_vm1->_net->getProviderName(args[0] - 1, name, sizeof(name));
return _vm1->setupStringArrayFromString(name);
}
int LogicHEmoonbase::op_net_set_provider(int op, int numArgs, int32 *args) {
return _vm1->_net->setProvider(args[0] - 1);
}
int LogicHEmoonbase::op_net_close_provider(int op, int numArgs, int32 *args) {
return _vm1->_net->closeProvider();
}
int LogicHEmoonbase::op_net_start_query_sessions(int op, int numArgs, int32 *args) {
return _vm1->_net->startQuerySessions();
}
int LogicHEmoonbase::op_net_update_query_sessions(int op, int numArgs, int32 *args) {
return _vm1->_net->updateQuerySessions();
}
int LogicHEmoonbase::op_net_stop_query_sessions(int op, int numArgs, int32 *args) {
_vm1->_net->stopQuerySessions();
return 1;
}
int LogicHEmoonbase::op_net_query_sessions(int op, int numArgs, int32 *args) {
return _vm1->_net->querySessions();
}
int LogicHEmoonbase::op_net_get_session_name(int op, int numArgs, int32 *args) {
char name[MAX_PROVIDER_NAME];
_vm1->_net->getSessionName(args[0] - 1, name, sizeof(name));
return _vm1->setupStringArrayFromString(name);
}
int LogicHEmoonbase::op_net_get_session_player_count(int op, int numArgs, int32 *args) {
return _vm1->_net->getSessionPlayerCount(args[0] - 1);
}
int LogicHEmoonbase::op_net_destroy_player(int op, int numArgs, int32 *args) {
return _vm1->_net->destroyPlayer(args[0]);
}
int LogicHEmoonbase::op_net_get_player_long_name(int op, int numArgs, int32 *args) {
return _vm1->setupStringArrayFromString("long name"); // TODO: gdefMultiPlay.playername1
}
int LogicHEmoonbase::op_net_get_player_short_name(int op, int numArgs, int32 *args) {
return _vm1->setupStringArrayFromString("short"); // TODO: gdefMultiPlay.playername2
}
int LogicHEmoonbase::op_net_create_session(int op, int numArgs, int32 *args) {
char name[MAX_SESSION_NAME];
_vm1->getStringFromArray(args[0], name, sizeof(name));
return _vm1->_net->createSession(name);
}
int LogicHEmoonbase::op_net_join_session(int op, int numArgs, int32 *args) {
return _vm1->_net->joinSession(args[0] - 1);
}
int LogicHEmoonbase::op_net_end_session(int op, int numArgs, int32 *args) {
return _vm1->_net->endSession();
}
int LogicHEmoonbase::op_net_disable_session_player_join(int op, int numArgs, int32 *args) {
_vm1->_net->disableSessionJoining();
return 1;
}
int LogicHEmoonbase::op_net_enable_session_player_join(int op, int numArgs, int32 *args) {
_vm1->_net->enableSessionJoining();
return 1;
}
int LogicHEmoonbase::op_net_set_ai_player_count(int op, int numArgs, int32 *args) {
_vm1->_net->setBotsCount(args[0]);
return 1;
}
int LogicHEmoonbase::op_net_add_user(int op, int numArgs, int32 *args) {
char userName[MAX_PLAYER_NAME];
_vm1->getStringFromArray(args[0], userName, sizeof(userName));
return _vm1->_net->addUser(userName, userName);
}
int LogicHEmoonbase::op_net_remove_user(int op, int numArgs, int32 *args) {
return _vm1->_net->removeUser();
}
int LogicHEmoonbase::op_net_who_sent_this(int op, int numArgs, int32 *args) {
return _vm1->_net->whoSentThis();
}
int LogicHEmoonbase::op_net_who_am_i(int op, int numArgs, int32 *args) {
return _vm1->_net->whoAmI();
}
int LogicHEmoonbase::op_net_set_provider_by_name(int op, int numArgs, int32 *args) {
// Parameter 1 is the provider name and
// Parameter 2 is the (optional) tcp/ip address
return _vm1->_net->setProviderByName(args[0], args[1]);
}
void LogicHEmoonbase::op_net_set_fake_latency(int op, int numArgs, int32 *args) {
_vm1->_net->setFakeLatency(args[0]);
}
int LogicHEmoonbase::op_net_get_host_name(int op, int numArgs, int32 *args) {
char name[MAX_HOSTNAME_SIZE];
if (_vm1->_net->getHostName(name, MAX_HOSTNAME_SIZE)) {
return _vm1->setupStringArrayFromString(name);
}
return 0;
}
int LogicHEmoonbase::op_net_get_ip_from_name(int op, int numArgs, int32 *args) {
char name[MAX_HOSTNAME_SIZE];
_vm1->getStringFromArray(args[0], name, sizeof(name));
char ip[MAX_IP_SIZE];
if (_vm1->_net->getIPfromName(ip, MAX_IP_SIZE, name)) {
return _vm1->setupStringArrayFromString(ip);
}
return 0;
}
int LogicHEmoonbase::op_net_host_tcpip_game(int op, int numArgs, int32 *args) {
char sessionName[MAX_SESSION_NAME];
char userName[MAX_PLAYER_NAME];
_vm1->getStringFromArray(args[0], sessionName, sizeof(sessionName));
_vm1->getStringFromArray(args[1], userName, sizeof(userName));
return _vm1->_net->hostGame(sessionName, userName);
}
int LogicHEmoonbase::op_net_join_tcpip_game(int op, int numArgs, int32 *args) {
char ip[MAX_IP_SIZE];
char userName[MAX_PLAYER_NAME];
_vm1->getStringFromArray(args[0], ip, sizeof(ip));
_vm1->getStringFromArray(args[1], userName, sizeof(userName));
return _vm1->_net->joinGame(ip, userName);
}
#endif
LogicHE *makeLogicHEmoonbase(ScummEngine_v100he *vm) {
return new LogicHEmoonbase(vm);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,375 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "scumm/he/intern_he.h"
#include "scumm/he/logic_he.h"
namespace Scumm {
/**
* Logic code for:
* Putt-Putt Enters the Race
*/
class LogicHErace : public LogicHE {
private:
float *_userData;
double *_userDataD;
public:
LogicHErace(ScummEngine_v90he *vm);
~LogicHErace() override;
int versionID() override;
int32 dispatch(int op, int numArgs, int32 *args) override;
private:
int32 op_1003(int32 *args);
int32 op_1004(int32 *args);
int32 op_1100(int32 *args);
int32 op_1101(int32 *args);
int32 op_1102(int32 *args);
int32 op_1103(int32 *args);
int32 op_1110();
int32 op_1120(int32 *args);
int32 op_1130(int32 *args);
int32 op_1140(int32 *args);
void op_sub1(float arg);
void op_sub2(float arg);
void op_sub3(float arg);
};
LogicHErace::LogicHErace(ScummEngine_v90he *vm) : LogicHE(vm) {
// Originally it used 0x930 and stored both floats and doubles inside
_userData = (float *)calloc(550, sizeof(float));
_userDataD = (double *)calloc(30, sizeof(double));
// FIXME: of the 550 entries in _userData, only 516 till 532 are used
// FIXME: similarly, in _userDataD only 9 till 17 are used for computations
// (some of the other entries are also set, but never read, hence useless).
}
LogicHErace::~LogicHErace() {
free(_userData);
free(_userDataD);
}
int LogicHErace::versionID() {
return 1;
}
int32 LogicHErace::dispatch(int op, int numArgs, int32 *args) {
int32 res;
switch (op) {
case 1003:
res = op_1003(args);
break;
case 1004:
res = op_1004(args);
break;
case 1100:
res = op_1100(args);
break;
case 1101:
res = op_1101(args);
break;
case 1102:
res = op_1102(args);
break;
case 1103:
res = op_1103(args);
break;
case 1110:
res = op_1110();
break;
case 1120:
res = op_1120(args);
break;
case 1130:
res = op_1130(args);
break;
case 1140:
res = op_1140(args);
break;
default:
res = 0;
break;
}
return res;
}
#define RAD2DEG (180 / M_PI)
#define DEG2RAD (M_PI / 180)
int32 LogicHErace::op_1003(int32 *args) {
int value = args[2] ? args[2] : 1;
writeScummVar(108, (int32)(atan2((double)args[0], (double)args[1]) * RAD2DEG * value));
return 1;
}
int32 LogicHErace::op_1004(int32 *args) {
int value = args[1] ? args[1] : 1;
writeScummVar(108, (int32)(sqrt((float)args[0]) * value));
return 1;
}
int32 LogicHErace::op_1100(int32 *args) {
// _userData 516,517,518 describe a 3D translation?
_userData[516] = (float)args[0] / args[10];
_userData[517] = (float)args[1] / args[10];
_userData[518] = (float)args[2] / args[10];
// _userData 519,520,521 describe rotation angles around the x,y,z axes?
_userData[519] = (float)args[3] / args[10];
_userData[520] = (float)args[4] / args[10];
_userData[521] = (float)args[5] / args[10];
op_sub1(_userData[520]);
op_sub2(_userData[521]);
// _userData[532] seems to be some kind of global scale factor
_userData[532] = (float)args[10];
_userData[524] = (float)args[8]; // not used
_userData[525] = (float)args[9]; // not used
_userData[522] = (float)args[6] / args[10]; // not used
_userData[523] = (float)args[7] / args[10]; // only used to compute 528 and 529
// The following two are some kind of scale factors
_userData[526] = (float)args[6] / args[8] / args[10];
_userData[527] = (float)args[7] / args[9] / args[10];
// Set var 108 and 109 -- the value set here corresponds to the values
// set by op_1110!
writeScummVar(108, (int32)((float)args[6] / args[8] * args[10]));
writeScummVar(109, (int32)((float)args[7] / args[9] * args[10]));
_userData[528] = (float)(_userData[519] - _userData[523] * 0.5);
_userData[529] = (float)(_userData[519] + _userData[523] * 0.5);
writeScummVar(110, (int32)(_userData[528] * args[10]));
writeScummVar(111, (int32)(_userData[529] * args[10]));
// 530 and 531 are only used to set vars 112 and 113, so no need
// to store them permanently
_userData[530] = (float)(_userData[517] / tan(_userData[529] * DEG2RAD));
_userData[531] = (float)(_userData[517] / tan(_userData[528] * DEG2RAD));
writeScummVar(112, (int32)(_userData[530] * args[10]));
writeScummVar(113, (int32)(_userData[531] * args[10]));
return 1;
}
int32 LogicHErace::op_1101(int32 *args) {
// Update rotation params?
int32 retval;
float temp;
temp = args[0] / _userData[532];
if (_userData[519] != temp) {
_userData[519] = temp;
op_sub3(temp);
retval = 1;
} else {
retval = (int32)temp;
}
temp = args[1] / _userData[532];
if (_userData[520] != temp) {
_userData[520] = temp;
op_sub1(temp);
retval = 1;
}
temp = args[2] / _userData[532];
if (_userData[521] != temp) {
_userData[521] = temp;
op_sub2(temp);
retval = 1;
}
return retval;
}
int32 LogicHErace::op_1102(int32 *args) {
// Update translation params?
int32 retval;
float temp;
temp = args[0] / _userData[532];
if (_userData[516] != temp) {
_userData[516] = temp;
retval = 1;
} else {
retval = (int32)_userData[532];
}
temp = args[1] / _userData[532];
if (_userData[517] != temp) {
_userData[517] = temp;
retval = 1;
}
temp = args[2] / _userData[532];
if (_userData[518] != temp) {
_userData[518] = temp;
retval = 1;
}
return retval;
}
int32 LogicHErace::op_1103(int32 *args) {
double angle = (double)args[0] / (double)args[1] * DEG2RAD;
writeScummVar(108, (int32)(sin(angle) * args[2]));
writeScummVar(109, (int32)(cos(angle) * args[2]));
return 1;
}
int32 LogicHErace::op_1110() {
writeScummVar(108, (int32)(_userData[526] * _userData[532] * _userData[532]));
writeScummVar(109, (int32)(_userData[527] * _userData[532] * _userData[532]));
writeScummVar(110, (int32)(_userData[532]));
return 1;
}
int32 LogicHErace::op_1120(int32 *args) {
double a0, a1, a2;
double b0, b1, b2;
double res1, res2;
a0 = args[0] / _userData[532] - _userData[516];
a1 = args[1] / _userData[532] - _userData[517];
a2 = args[2] / _userData[532] - _userData[518];
// Perform matrix multiplication (multiplying by a rotation matrix)
b2 = a2 * _userDataD[17] + a1 * _userDataD[14] + a0 * _userDataD[11];
b1 = a2 * _userDataD[16] + a1 * _userDataD[13] + a0 * _userDataD[10];
b0 = a2 * _userDataD[15] + a1 * _userDataD[12] + a0 * _userDataD[9];
res1 = (atan2(b0, b2) * RAD2DEG) / _userData[526];
res2 = (atan2(b1, b2) * RAD2DEG - _userData[528]) / _userData[527];
writeScummVar(108, (int32)res1);
writeScummVar(109, (int32)res2);
return 1;
}
int32 LogicHErace::op_1130(int32 *args) {
double cs = cos(args[0] / _userData[532] * DEG2RAD);
double sn = sin(args[0] / _userData[532] * DEG2RAD);
writeScummVar(108, (int32)(cs * args[1] + sn * args[2]));
writeScummVar(109, (int32)(cs * args[2] - sn * args[1]));
return 1;
}
int32 LogicHErace::op_1140(int32 *args) {
// This functions seems to perform some kind of projection: We project
// the vector (arg2,arg3) onto the vector (arg0,arg1), but also apply
// some kind of distortion factor ?!?
double x = args[2], y = args[3];
// We start by normalizing the vector described by arg2 and arg3.
// So compute its length and divide the x and y coordinates
const double sq = sqrt(x*x + y*y);
x /= sq;
y /= sq;
// Compute the scalar product of the vectors (arg0,arg1) and (x,y)
const double scalarProduct = x * args[0] + y * args[1];
// Finally compute the projection of (arg2,arg3) onto (arg0,arg1)
double projX = args[0] - 2 * scalarProduct * x;
double projY = args[1] - 2 * scalarProduct * y;
projX = projX * 20.0 / 23.0; // FIXME: Why is this here?
writeScummVar(108, (int32)projX);
if (args[3] >= 0) // FIXME: Why is this here?
projY = projY * 5.0 / 6.0;
writeScummVar(109, (int32)projY);
return 1;
}
void LogicHErace::op_sub1(float arg) {
// Setup a rotation matrix
_userDataD[10] = _userDataD[12] = _userDataD[14] = _userDataD[16] = 0;
_userDataD[13] = 1;
_userDataD[9] = cos(arg * DEG2RAD);
_userDataD[15] = sin(arg * DEG2RAD);
_userDataD[11] = -_userDataD[15];
_userDataD[17] = _userDataD[9];
}
void LogicHErace::op_sub2(float arg) {
// Setup a rotation matrix -- but it is NEVER USED!
_userDataD[20] = _userDataD[21] = _userDataD[24] = _userDataD[25] = 0;
_userDataD[26] = 1;
_userDataD[19] = sin(arg * DEG2RAD);
_userDataD[18] = cos(arg * DEG2RAD);
_userDataD[21] = -_userDataD[19];
_userDataD[22] = _userDataD[18];
}
void LogicHErace::op_sub3(float arg) {
// Setup a rotation matrix -- but it is NEVER USED!
_userDataD[1] = _userDataD[2] = _userDataD[3] = _userDataD[6] = 0;
_userDataD[0] = 1;
_userDataD[4] = cos(arg * DEG2RAD);
_userDataD[5] = sin(arg * DEG2RAD);
_userDataD[7] = -_userDataD[5];
_userDataD[8] = _userDataD[4];
}
LogicHE *makeLogicHErace(ScummEngine_v90he *vm) {
return new LogicHErace(vm);
}
} // End of namespace Scumm

File diff suppressed because it is too large Load Diff