mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 21:59:17 +00:00
246 lines
6.7 KiB
C++
246 lines
6.7 KiB
C++
/* ResidualVM - A 3D game interpreter
|
|
*
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
* file distributed with this source distribution.
|
|
*
|
|
* Additional copyright for this file:
|
|
* Copyright (C) 1999-2000 Revolution Software Ltd.
|
|
* This code is based on source code created by Revolution Software,
|
|
* used with permission.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "engines/icb/debug.h"
|
|
#include "engines/icb/mission.h"
|
|
#include "engines/icb/global_objects.h"
|
|
#include "engines/icb/global_vars.h"
|
|
#include "engines/icb/timer_func.h"
|
|
#include "engines/icb/common/ptr_util.h"
|
|
|
|
namespace ICB {
|
|
|
|
// whether the timer is on or off...
|
|
bool8 timerOn = FALSE8;
|
|
|
|
// hash of variable being followed...
|
|
uint32 timerVariable;
|
|
|
|
// divide the variable by this to get seconds (generally 12 for game cycles)
|
|
int32 timerMultiplier;
|
|
|
|
// below this value we display in red...
|
|
int32 timerDanger;
|
|
|
|
#define BAR_WIDTH 8
|
|
#define BAR_HEIGHT 6
|
|
#define DIG_SPACING (BAR_WIDTH + 4)
|
|
#define TIME_X (320 + 250)
|
|
#define TIME_Y (240 + 220)
|
|
|
|
// generic digits..............
|
|
#define TOP_BIT 1
|
|
#define TOP_RIGHT_BIT 2
|
|
#define TOP_LEFT_BIT 4
|
|
#define MID_BIT 8
|
|
#define BOT_RIGHT_BIT 16
|
|
#define BOT_LEFT_BIT 32
|
|
#define BOT_BIT 64
|
|
|
|
const uint8 digitBits[10] = {
|
|
// TOP_BIT | TOP_RIGHT_BIT | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | BOT_LEFT_BIT | BOT_BIT
|
|
TOP_BIT | TOP_RIGHT_BIT | TOP_LEFT_BIT | 0 | BOT_RIGHT_BIT | BOT_LEFT_BIT | BOT_BIT, // 0
|
|
0 | 0 | TOP_LEFT_BIT | 0 | 0 | BOT_LEFT_BIT | 0, // 1
|
|
TOP_BIT | TOP_RIGHT_BIT | 0 | MID_BIT | 0 | BOT_LEFT_BIT | BOT_BIT, // 2
|
|
TOP_BIT | TOP_RIGHT_BIT | 0 | MID_BIT | BOT_RIGHT_BIT | 0 | BOT_BIT, // 3
|
|
0 | TOP_RIGHT_BIT | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | 0 | 0, // 4
|
|
TOP_BIT | 0 | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | 0 | BOT_BIT, // 5
|
|
TOP_BIT | 0 | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | BOT_LEFT_BIT | BOT_BIT, // 6
|
|
TOP_BIT | TOP_RIGHT_BIT | 0 | 0 | BOT_RIGHT_BIT | 0 | 0, // 7
|
|
TOP_BIT | TOP_RIGHT_BIT | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | BOT_LEFT_BIT | BOT_BIT, // 8
|
|
TOP_BIT | TOP_RIGHT_BIT | TOP_LEFT_BIT | MID_BIT | BOT_RIGHT_BIT | 0 | BOT_BIT, // 9
|
|
|
|
};
|
|
|
|
const short barXY[7][2] = {
|
|
{1, 0}, // top
|
|
{BAR_WIDTH + 1, 1}, // top/right
|
|
{0, 1}, // top/left
|
|
{1, BAR_HEIGHT + 1}, // mid
|
|
{BAR_WIDTH + 1, BAR_HEIGHT + 2}, // bot/right
|
|
{0, BAR_HEIGHT + 2}, // bot/left
|
|
{1, 2 * BAR_HEIGHT + 2} // bot
|
|
};
|
|
|
|
// DRAW THE SEGMENT - different for psx and pc at the moment -----------------
|
|
|
|
#include "surface_manager.h"
|
|
|
|
void DrawSegment(int32 x, int32 y, int32 dx, int32 dy, int32 danger) {
|
|
uint8 *surface_address;
|
|
uint32 pitch;
|
|
|
|
surface_address = surface_manager->Lock_surface(working_buffer_id);
|
|
pitch = surface_manager->Get_pitch(working_buffer_id);
|
|
|
|
_rgb drawColour;
|
|
|
|
_rgb red = {255, 64, 64, 0};
|
|
_rgb green = {64, 255, 64, 0};
|
|
_rgb black = {0, 0, 0, 0};
|
|
|
|
if (danger)
|
|
drawColour = red;
|
|
else
|
|
drawColour = green;
|
|
|
|
if (dx == 0) {
|
|
Draw_vertical_line(x - 1, y, dy, &black, surface_address, pitch);
|
|
Draw_vertical_line(x, y, dy, &drawColour, surface_address, pitch);
|
|
Draw_vertical_line(x + 1, y, dy, &black, surface_address, pitch);
|
|
} else {
|
|
Draw_horizontal_line(x, y - 1, dx, &black, surface_address, pitch);
|
|
Draw_horizontal_line(x, y, dx, &drawColour, surface_address, pitch);
|
|
Draw_horizontal_line(x, y + 1, dx, &black, surface_address, pitch);
|
|
}
|
|
surface_manager->Unlock_surface(working_buffer_id);
|
|
}
|
|
|
|
// draw a digit using lcd display, -1 for the :
|
|
void DrawDigit(int32 x, int32 y, int32 d, int32 danger) {
|
|
int32 sx, sy, dx, dy;
|
|
int32 i, dig;
|
|
|
|
// special dash...
|
|
if (d == -1) {
|
|
DrawSegment(x + 1 + BAR_WIDTH / 2, y + 1, 0, BAR_HEIGHT - 1, danger);
|
|
DrawSegment(x + 1 + BAR_WIDTH / 2, y + BAR_HEIGHT + 2, 0, BAR_HEIGHT - 1, danger);
|
|
return;
|
|
}
|
|
|
|
// move the 1 back 4 pixels
|
|
if (d == 1)
|
|
x += 1 + BAR_WIDTH / 2;
|
|
|
|
for (i = 0; i < 7; i++) {
|
|
dig = (1 << i);
|
|
|
|
if (digitBits[d] & dig) {
|
|
sx = x + barXY[i][0];
|
|
sy = y + barXY[i][1];
|
|
if ((dig == TOP_BIT) || (dig == BOT_BIT) || (dig == MID_BIT)) {
|
|
dx = BAR_WIDTH;
|
|
dy = 0;
|
|
} else {
|
|
dx = 0;
|
|
dy = BAR_HEIGHT;
|
|
}
|
|
|
|
DrawSegment(sx, sy, dx, dy, danger);
|
|
}
|
|
}
|
|
}
|
|
|
|
// draw mm:ss
|
|
void DrawTime(int32 mins, int32 secs, int32 hs, int32 danger) {
|
|
int32 x, y;
|
|
|
|
x = TIME_X;
|
|
y = TIME_Y;
|
|
|
|
DrawDigit(x, y, mins / 10, danger);
|
|
|
|
x += DIG_SPACING;
|
|
|
|
DrawDigit(x, y, mins % 10, danger);
|
|
|
|
x += DIG_SPACING;
|
|
|
|
if (hs)
|
|
DrawDigit(x, y, -1, danger); // dash
|
|
|
|
x += DIG_SPACING;
|
|
|
|
DrawDigit(x, y, secs / 10, danger);
|
|
|
|
x += DIG_SPACING;
|
|
|
|
DrawDigit(x, y, secs % 10, danger);
|
|
}
|
|
|
|
// call this to draw timer if it is on
|
|
void DrawTimer() {
|
|
if (!timerOn)
|
|
return;
|
|
|
|
int32 mins, secs, cycles, totalSecs, hs, danger;
|
|
|
|
cycles = g_globalScriptVariables->GetVariable(timerVariable);
|
|
|
|
totalSecs = cycles / timerMultiplier;
|
|
|
|
mins = totalSecs / 60;
|
|
secs = totalSecs % 60;
|
|
|
|
if ((cycles % timerMultiplier) < (timerMultiplier / 2))
|
|
hs = 1;
|
|
else
|
|
hs = 0;
|
|
|
|
if (cycles < timerDanger)
|
|
danger = 1;
|
|
else
|
|
danger = 0;
|
|
|
|
DrawTime(mins, secs, hs, danger);
|
|
}
|
|
|
|
void StopTimer() {
|
|
// timer off
|
|
timerOn = FALSE8;
|
|
}
|
|
|
|
mcodeFunctionReturnCodes fn_stop_timer(int32 &, int32 *) {
|
|
StopTimer();
|
|
|
|
return (IR_CONT);
|
|
}
|
|
|
|
mcodeFunctionReturnCodes fn_activate_timer(int32 &, int32 *params) {
|
|
const char *timer_name = (const char *)MemoryUtil::resolvePtr(params[0]);
|
|
|
|
// timer is now on
|
|
timerOn = TRUE8;
|
|
|
|
// variable
|
|
timerVariable = HashString(timer_name);
|
|
|
|
// test variable exists...
|
|
int32 test = g_globalScriptVariables->FindVariable(timerVariable);
|
|
if (test == -1) {
|
|
Fatal_error("No global variable %s which fn_activate_timer() has been told to follow!", timer_name);
|
|
}
|
|
|
|
// set other values...
|
|
timerMultiplier = (int32)params[1];
|
|
timerDanger = (int32)params[2];
|
|
|
|
return (IR_CONT);
|
|
}
|
|
|
|
} // End of namespace ICB
|