mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-11 19:54:03 +00:00
1490 lines
34 KiB
C++
1490 lines
34 KiB
C++
/* 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 "engines/metaengine.h"
|
|
#include "base/plugins.h"
|
|
#include "base/version.h"
|
|
#include "common/events.h"
|
|
#include "common/system.h"
|
|
#include "common/translation.h"
|
|
#include "common/util.h"
|
|
#include "graphics/surface.h"
|
|
#include "graphics/fonts/amigafont.h"
|
|
#include "gui/about.h"
|
|
#include "gui/gui-manager.h"
|
|
#include "gui/ThemeEval.h"
|
|
|
|
namespace GUI {
|
|
|
|
class EE;
|
|
|
|
class EEHandler {
|
|
public:
|
|
bool handleKeyDown(Common::KeyState &state);
|
|
};
|
|
|
|
enum {
|
|
kScrollStartDelay = 1500,
|
|
kScrollMillisPerPixel = 60
|
|
};
|
|
|
|
// Every Line should start with a letter followed by a digit. Currently those can be
|
|
// (all subject to change)
|
|
// Letter:
|
|
// C, L, R -- set center/left/right alignment
|
|
// A -- ASCII text to replace the next (latin1) line
|
|
// Digit:
|
|
// 0 - 2 -- set a custom color:
|
|
// 0 normal text
|
|
// 1 highlighted text
|
|
// 2 disabled text
|
|
// TODO: Maybe add a tab/indent feature; that is, make it possible to specify
|
|
// an amount by which that line shall be indented (the indent of course would have
|
|
// to be considered while performing any word wrapping, too).
|
|
//
|
|
// TODO: Add different font sizes (for bigger headlines)
|
|
// TODO: Allow color change in the middle of a line...
|
|
|
|
static const char *const copyright_text[] = {
|
|
"",
|
|
"C0""Copyright (C) 2001-2024 The ScummVM Team",
|
|
"C0""https://www.scummvm.org",
|
|
"",
|
|
"C0""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 binary.",
|
|
"",
|
|
};
|
|
|
|
static const char *const gpl_text[] = {
|
|
"",
|
|
"C0""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.",
|
|
"C0""",
|
|
"C0""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.",
|
|
"",
|
|
"C0""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 "gui/credits.h"
|
|
|
|
AboutDialog::AboutDialog()
|
|
: Dialog(10, 20, 300, 174),
|
|
_scrollPos(0), _scrollTime(0), _willClose(false), _autoScroll(true) {
|
|
|
|
reflowLayout();
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 1; i++)
|
|
_lines.push_back(Common::U32String());
|
|
|
|
Common::String version("C0""ScummVM ");
|
|
version += gScummVMVersion;
|
|
addLine(version);
|
|
|
|
// I18N: built on <build date> with <compiler>
|
|
Common::U32String date = Common::U32String::format(_("(built on %s with %s)"), gScummVMBuildDate, gScummVMCompiler);
|
|
addLine(Common::U32String("C2") + date);
|
|
|
|
for (i = 0; i < ARRAYSIZE(copyright_text); i++)
|
|
addLine(Common::U32String(copyright_text[i]));
|
|
|
|
Common::U32String features("C1");
|
|
features += _("Features compiled in:");
|
|
addLine(features);
|
|
Common::String featureList("C0");
|
|
featureList += gScummVMFeatures;
|
|
addLine(featureList);
|
|
|
|
_lines.push_back(Common::U32String());
|
|
|
|
Common::U32String extensionSupportString[3] = { _("not supported"), _("disabled"), _("enabled") };
|
|
|
|
byte sse2Support = 0;
|
|
byte avx2Support = 0;
|
|
byte neonSupport = 0;
|
|
|
|
#ifdef SCUMMVM_SSE2
|
|
++sse2Support;
|
|
if (g_system->hasFeature(OSystem::kFeatureCpuSSE2))
|
|
++sse2Support;
|
|
#endif
|
|
#ifdef SCUMMVM_AVX2
|
|
++avx2Support;
|
|
if (g_system->hasFeature(OSystem::kFeatureCpuAVX2))
|
|
++avx2Support;
|
|
#endif
|
|
#ifdef SCUMMVM_NEON
|
|
++neonSupport;
|
|
if (g_system->hasFeature(OSystem::kFeatureCpuNEON))
|
|
++neonSupport;
|
|
#endif
|
|
|
|
Common::U32String extensionsInfo("C1");
|
|
// I18N: CPU extensions are sets of extra processor instructions used to speed up operations. See Intel AVX2, ARM NEON, etc.
|
|
extensionsInfo += _("CPU extensions support:");
|
|
addLine(extensionsInfo);
|
|
Common::U32String compiledExtensionsList("C0");
|
|
compiledExtensionsList += Common::U32String::format("SSE2(%S) AVX2(%S) NEON(%S)",
|
|
extensionSupportString[sse2Support].c_str(),
|
|
extensionSupportString[avx2Support].c_str(),
|
|
extensionSupportString[neonSupport].c_str());
|
|
|
|
addLine(compiledExtensionsList);
|
|
|
|
_lines.push_back(Common::U32String());
|
|
|
|
Common::U32String engines("C1");
|
|
engines += _("Available engines:");
|
|
addLine(engines);
|
|
|
|
const PluginList &plugins = EngineMan.getPlugins(PLUGIN_TYPE_ENGINE);
|
|
PluginList::const_iterator iter = plugins.begin();
|
|
for (; iter != plugins.end(); ++iter) {
|
|
Common::String str;
|
|
|
|
const Plugin *p = EngineMan.findPlugin((*iter)->getName());
|
|
|
|
if (!p) {
|
|
warning("Cannot find plugin for %s", (*iter)->getName());
|
|
continue;
|
|
}
|
|
|
|
str = "C0";
|
|
str += p->get<MetaEngineDetection>().getEngineName();
|
|
addLine(str);
|
|
str = "C2";
|
|
str += p->get<MetaEngineDetection>().getOriginalCopyright();
|
|
addLine(str);
|
|
|
|
//addLine("");
|
|
}
|
|
|
|
for (i = 0; i < ARRAYSIZE(gpl_text); i++)
|
|
addLine(Common::U32String(gpl_text[i]));
|
|
|
|
_lines.push_back(Common::U32String());
|
|
|
|
for (i = 0; i < ARRAYSIZE(credits); i++)
|
|
addLine(Common::U32String(credits[i], Common::kUtf8));
|
|
}
|
|
|
|
void AboutDialog::addLine(const Common::U32String &str) {
|
|
Common::U32String::const_iterator strBeginItr = str.begin();
|
|
if (*strBeginItr == 0) {
|
|
_lines.push_back(Common::U32String());
|
|
} else {
|
|
Common::U32String format(str.begin(), str.begin() + 2);
|
|
strBeginItr += 2;
|
|
Common::U32String renderStr(strBeginItr, str.end());
|
|
|
|
Common::U32StringArray wrappedLines;
|
|
g_gui.getFont().wordWrapText(renderStr, _w - 2 * _xOff, wrappedLines);
|
|
|
|
for (Common::U32StringArray::const_iterator i = wrappedLines.begin(); i != wrappedLines.end(); ++i) {
|
|
_lines.push_back(format + *i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void AboutDialog::open() {
|
|
_scrollTime = g_system->getMillis() + kScrollStartDelay;
|
|
_scrollPos = 0;
|
|
_willClose = false;
|
|
|
|
Dialog::open();
|
|
}
|
|
|
|
void AboutDialog::close() {
|
|
Dialog::close();
|
|
}
|
|
|
|
void AboutDialog::drawDialog(DrawLayer layerToDraw) {
|
|
Dialog::drawDialog(layerToDraw);
|
|
|
|
setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h));
|
|
|
|
// Draw text
|
|
// TODO: Add a "fade" effect for the top/bottom text lines
|
|
// TODO: Maybe prerender all of the text into another surface,
|
|
// and then simply compose that over the screen surface
|
|
// in the right way. Should be even faster...
|
|
const int firstLine = _scrollPos / _lineHeight;
|
|
const int lastLine = MIN((_scrollPos + _h) / _lineHeight + 1, (uint32)_lines.size());
|
|
int y = _y + _yOff - (_scrollPos % _lineHeight);
|
|
|
|
for (int line = firstLine; line < lastLine; line++) {
|
|
Common::U32String str = _lines[line];
|
|
Common::U32String::const_iterator strLineItrBegin = _lines[line].begin();
|
|
Common::U32String::const_iterator strLineItrEnd = _lines[line].end();
|
|
|
|
Graphics::TextAlign align = Graphics::kTextAlignCenter;
|
|
ThemeEngine::WidgetStateInfo state = ThemeEngine::kStateEnabled;
|
|
if (strLineItrBegin != strLineItrEnd) {
|
|
switch (*strLineItrBegin) {
|
|
case 'C':
|
|
align = Graphics::kTextAlignCenter;
|
|
break;
|
|
case 'L':
|
|
align = Graphics::kTextAlignLeft;
|
|
break;
|
|
case 'R':
|
|
align = Graphics::kTextAlignRight;
|
|
break;
|
|
default:
|
|
error("Unknown scroller opcode '%c'", str[0]);
|
|
break;
|
|
}
|
|
switch (*(strLineItrBegin + 1)) {
|
|
case '0':
|
|
state = ThemeEngine::kStateEnabled;
|
|
break;
|
|
case '1':
|
|
state = ThemeEngine::kStateHighlight;
|
|
break;
|
|
case '2':
|
|
state = ThemeEngine::kStateDisabled;
|
|
break;
|
|
case '3':
|
|
warning("Need state for color 3");
|
|
// color = g_gui._shadowcolor;
|
|
break;
|
|
case '4':
|
|
warning("Need state for color 4");
|
|
// color = g_gui._bgcolor;
|
|
break;
|
|
default:
|
|
error("Unknown color type '%c'", str[1]);
|
|
}
|
|
strLineItrBegin += 2;
|
|
}
|
|
// Trim leading whitespaces if center mode is on
|
|
if (align == Graphics::kTextAlignCenter)
|
|
while (strLineItrBegin != strLineItrEnd && *strLineItrBegin == ' ')
|
|
strLineItrBegin++;
|
|
|
|
Common::U32String renderStr(strLineItrBegin, strLineItrEnd);
|
|
if (!renderStr.empty())
|
|
g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()),
|
|
renderStr, state, align, ThemeEngine::kTextInversionNone, 0, false,
|
|
ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea);
|
|
y += _lineHeight;
|
|
}
|
|
}
|
|
|
|
void AboutDialog::handleTickle() {
|
|
const uint32 t = g_system->getMillis();
|
|
int scrollOffset = ((int)t - (int)_scrollTime) / kScrollMillisPerPixel;
|
|
if (_autoScroll && scrollOffset > 0) {
|
|
int modifiers = g_system->getEventManager()->getModifierState();
|
|
|
|
// Scroll faster when shift is pressed
|
|
if (modifiers & Common::KBD_SHIFT)
|
|
scrollOffset *= 4;
|
|
// Reverse scrolling when alt is pressed
|
|
if (modifiers & Common::KBD_ALT)
|
|
scrollOffset *= -1;
|
|
_scrollPos += scrollOffset;
|
|
_scrollTime = t;
|
|
|
|
if (_scrollPos < 0) {
|
|
_scrollPos = 0;
|
|
} else if ((uint32)_scrollPos > _lines.size() * _lineHeight) {
|
|
_scrollPos = 0;
|
|
_scrollTime += kScrollStartDelay;
|
|
}
|
|
drawDialog(kDrawLayerForeground);
|
|
}
|
|
}
|
|
|
|
void AboutDialog::handleMouseUp(int x, int y, int button, int clickCount) {
|
|
// Close upon any mouse click
|
|
close();
|
|
}
|
|
|
|
void AboutDialog::handleMouseWheel(int x, int y, int direction) {
|
|
const int stepping = 5 * _lineHeight * direction;
|
|
|
|
if (stepping == 0)
|
|
return;
|
|
|
|
_autoScroll = false;
|
|
|
|
int newScrollPos = _scrollPos + stepping;
|
|
|
|
if (newScrollPos < 0) {
|
|
_scrollPos = 0;
|
|
} else if ((uint32)newScrollPos < _lines.size() * _lineHeight) {
|
|
_scrollPos = newScrollPos;
|
|
}
|
|
drawDialog(kDrawLayerForeground);
|
|
}
|
|
|
|
void AboutDialog::handleKeyDown(Common::KeyState state) {
|
|
EEHandler eeHandler;
|
|
|
|
if (eeHandler.handleKeyDown(state)) {
|
|
reflowLayout();
|
|
return;
|
|
}
|
|
|
|
if (state.ascii)
|
|
_willClose = true;
|
|
}
|
|
|
|
void AboutDialog::handleKeyUp(Common::KeyState state) {
|
|
if (state.ascii && _willClose)
|
|
close();
|
|
}
|
|
|
|
void AboutDialog::reflowLayout() {
|
|
Dialog::reflowLayout();
|
|
int i;
|
|
const int screenW = g_system->getOverlayWidth();
|
|
const int screenH = g_system->getOverlayHeight();
|
|
|
|
_xOff = g_gui.xmlEval()->getVar("Globals.About.XOffset", 5);
|
|
_yOff = g_gui.xmlEval()->getVar("Globals.About.YOffset", 5);
|
|
int outerBorder = g_gui.xmlEval()->getVar("Globals.About.OuterBorder");
|
|
|
|
_w = screenW - 2 * outerBorder;
|
|
_h = screenH - 2 * outerBorder;
|
|
|
|
_lineHeight = g_gui.getFontHeight() + 3;
|
|
|
|
// Heuristic to compute 'optimal' dialog width
|
|
int maxW = _w - 2*_xOff;
|
|
_w = 0;
|
|
for (i = 0; i < ARRAYSIZE(credits); i++) {
|
|
int tmp = g_gui.getStringWidth(credits[i]) + 5;
|
|
if (_w < tmp && tmp <= maxW) {
|
|
_w = tmp;
|
|
}
|
|
}
|
|
_w += 2*_xOff;
|
|
|
|
// Center the dialog
|
|
_x = (screenW - _w) / 2;
|
|
_y = (screenH - _h) / 2;
|
|
}
|
|
|
|
|
|
////////////////////////////////
|
|
//// Here we go
|
|
////////////////////////////////
|
|
|
|
enum {
|
|
kDirUp, kDirLeft, kDirRight
|
|
};
|
|
|
|
enum {
|
|
kModeMenu, kModePlay, kModePause
|
|
};
|
|
|
|
enum { kPlComp, kPlHuman };
|
|
|
|
enum { kSndPoint, kSndHit, kSndLoss };
|
|
|
|
|
|
enum {
|
|
kSpL1, kSpL2, kSpL3,
|
|
kSpR1, kSpR2, kSpR3,
|
|
kSpB1, kSpB2, kSpB3, kSpB4,
|
|
kSp0, kSp1, kSp2, kSp3, kSp4,
|
|
kSp5, kSp6, kSp7, kSp8, kSp9,
|
|
kSpCode1,
|
|
kSpCode1h = kSpCode1 + 6,
|
|
kSpNum0 = kSpCode1h + 6,
|
|
kSpStar = kSpNum0 + 10,
|
|
kSpSpace,
|
|
kSpLast
|
|
};
|
|
class EE {
|
|
public:
|
|
EE();
|
|
~EE();
|
|
|
|
void run();
|
|
|
|
private:
|
|
Graphics::Surface _back;
|
|
int _hits;
|
|
bool _rmode; // animation after loosing
|
|
int _score[2];
|
|
|
|
bool _soundEnabled;
|
|
bool _shouldQuit;
|
|
|
|
int _rcnt; //last 20 cycles of round
|
|
int _winner; //who wins the point or serving
|
|
int _tvelx, _tvely;
|
|
|
|
int _x[2], _y[2], _px[2];
|
|
int _frame[2], _frameindex[2];
|
|
int _rebound[2];
|
|
int _bx, _by, _pbx, _pby, _tbx, _tby, _bvelx, _bvely;
|
|
int _serve, _server, _servevel, _compserve;
|
|
int _hitter, _starter, _sstage;
|
|
int _bytop;
|
|
int _rnd;
|
|
|
|
int _olx, _oly, _orx, _ory, _obx, _oby;
|
|
|
|
bool _air;
|
|
|
|
bool _oCoords;
|
|
|
|
int _mode;
|
|
|
|
int _keymove[2][3];
|
|
int _opts;
|
|
int _opt;
|
|
|
|
Graphics::AmigaFont _font;
|
|
|
|
Graphics::Surface _sp[kSpLast];
|
|
|
|
Graphics::PixelFormat _format;
|
|
int _windowX, _windowY, _windowW, _windowH;
|
|
float _scale;
|
|
bool _inited;
|
|
|
|
uint32 _colorBlack, _colorBlue, _colorOrange, _colorKey;
|
|
|
|
void cls(bool update = true);
|
|
void loadSounds();
|
|
void processKeyUp(Common::Event &e);
|
|
void processKeyDown(Common::Event &e);
|
|
void getPos();
|
|
void setwinner();
|
|
void resetpt();
|
|
void calcscore();
|
|
int destination(int pl, int destx, int tol);
|
|
bool moveball();
|
|
void docollisions();
|
|
void computer0();
|
|
void computer1();
|
|
void init();
|
|
void draw(int sn, int x, int y);
|
|
void doMenu(Common::Event &e);
|
|
void putshapes();
|
|
void game();
|
|
void playSound(int d);
|
|
|
|
void setupGraphics();
|
|
void genField();
|
|
};
|
|
|
|
bool EEHandler::handleKeyDown(Common::KeyState &state) {
|
|
if (state.ascii == 'v') {
|
|
EE *ee = new EE();
|
|
ee->run();
|
|
delete ee;
|
|
|
|
g_gui.redrawFull();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
EE::EE() {
|
|
init();
|
|
|
|
_scale = 1.0;
|
|
_windowW = 320;
|
|
_windowH = 200;
|
|
_windowX = _windowY = 0;
|
|
|
|
_format = g_system->getOverlayFormat();
|
|
|
|
_colorBlack = _colorBlue = _colorOrange = _colorKey = 0;
|
|
}
|
|
|
|
EE::~EE() {
|
|
for (int i = 0; i < kSpLast; i++)
|
|
_sp[i].free();
|
|
}
|
|
|
|
void EE::cls(bool update) {
|
|
_back.fillRect(Common::Rect(0, 0, _windowW, _windowH), _colorBlack);
|
|
|
|
if (update)
|
|
g_system->copyRectToOverlay(_back.getPixels(), _back.pitch, _windowX, _windowY, _windowW, _windowH);
|
|
}
|
|
|
|
void EE::run() {
|
|
if (!_inited)
|
|
return;
|
|
|
|
_shouldQuit = false;
|
|
|
|
setupGraphics();
|
|
|
|
init();
|
|
|
|
while (!_shouldQuit) {
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_QUIT:
|
|
case Common::EVENT_RETURN_TO_LAUNCHER:
|
|
_shouldQuit = true;
|
|
break;
|
|
case Common::EVENT_SCREEN_CHANGED:
|
|
if (g_gui.checkScreenChange())
|
|
setupGraphics();
|
|
break;
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
break;
|
|
case Common::EVENT_KEYDOWN:
|
|
processKeyDown(event);
|
|
break;
|
|
case Common::EVENT_KEYUP:
|
|
processKeyUp(event);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
game();
|
|
putshapes();
|
|
|
|
g_system->updateScreen();
|
|
g_system->delayMillis(10);
|
|
}
|
|
}
|
|
|
|
const int polecol[] = {0, 1, 2, 3, 3, 4, 6, 7, 9, 14};
|
|
const int jump[] = {-4, -4, -3, -3, -3, -3, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0,
|
|
0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4};
|
|
|
|
void EE::loadSounds() {
|
|
#if 0
|
|
if ($.isEmptyObject(sounds)) {
|
|
for (i = 0; i < snNames.length; i++) {
|
|
s = snNames[i];
|
|
sounds[s] = new Audio();
|
|
sounds[s].src = 'sounds/' + s + '.wav';
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void EE::processKeyUp(Common::Event &e) {
|
|
switch (e.kbd.keycode) {
|
|
case Common::KEYCODE_LEFT: // left
|
|
_keymove[1][kDirLeft] = 0;
|
|
break;
|
|
case Common::KEYCODE_RIGHT: // right
|
|
_keymove[1][kDirRight] = 0;
|
|
break;
|
|
case Common::KEYCODE_UP: // top
|
|
_keymove[1][kDirUp] = 0;
|
|
break;
|
|
case Common::KEYCODE_a: //a
|
|
_keymove[0][kDirLeft] = 0;
|
|
break;
|
|
case Common::KEYCODE_d: // d
|
|
_keymove[0][kDirRight] = 0;
|
|
break;
|
|
case Common::KEYCODE_w: // w
|
|
_keymove[0][kDirUp] = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EE::processKeyDown(Common::Event &e) {
|
|
if (_mode == kModeMenu) {
|
|
doMenu(e);
|
|
return;
|
|
}
|
|
|
|
switch (e.kbd.keycode) {
|
|
case Common::KEYCODE_LEFT: // left
|
|
_keymove[1][kDirLeft] = -2;
|
|
break;
|
|
case Common::KEYCODE_RIGHT: // right
|
|
_keymove[1][kDirRight] = 2;
|
|
break;
|
|
case Common::KEYCODE_UP: // top
|
|
_keymove[1][kDirUp]= 1;
|
|
break;
|
|
case Common::KEYCODE_a: //a
|
|
_keymove[0][kDirLeft] = -2;
|
|
break;
|
|
case Common::KEYCODE_d: // d
|
|
_keymove[0][kDirRight] = 2;
|
|
break;
|
|
case Common::KEYCODE_w: // w
|
|
_keymove[0][kDirUp] = 1;
|
|
break;
|
|
case Common::KEYCODE_ESCAPE:
|
|
_mode = kModeMenu;
|
|
break;
|
|
case Common::KEYCODE_p: // p
|
|
_keymove[0][kDirRight] = _keymove[0][kDirLeft] = _keymove[0][kDirUp] = 0;
|
|
_mode = (_mode == kModePlay) ? kModePause : kModePlay;
|
|
break;
|
|
case Common::KEYCODE_r: // r
|
|
if (_mode == kModePlay)
|
|
init();
|
|
break;
|
|
case Common::KEYCODE_s: // s
|
|
if (!_soundEnabled)
|
|
loadSounds();
|
|
_soundEnabled = !_soundEnabled;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EE::getPos() {
|
|
for (int i = 0; i < 2; i++) {
|
|
if (_keymove[i][kDirUp] && _frameindex[i] == -1)
|
|
_frameindex[i] = 0;
|
|
int velx = _keymove[i][kDirLeft] + _keymove[i][kDirRight];
|
|
int tx = _x[i] + velx;
|
|
int bnd = 3 + i * 155;
|
|
if (velx > 0) {
|
|
if (tx < bnd + 119)
|
|
_x[i] = tx;
|
|
else
|
|
_x[i] = bnd + 119;
|
|
} else if (tx > bnd) {
|
|
_x[i] = tx;
|
|
} else {
|
|
_x[i] = bnd;
|
|
}
|
|
|
|
if (_frameindex[i] == -2) {
|
|
_y[i] = 173;
|
|
_frame[i] = 0;
|
|
_frameindex[i] = -1;
|
|
}
|
|
if (_frameindex[i] == -1) {
|
|
if (velx != 0) {
|
|
if (abs(_px[i] - _x[i]) > 4) {
|
|
_frame[i] ^= 1;
|
|
_px[i] = _x[i];
|
|
}
|
|
} else {
|
|
_frame[i] = 0;
|
|
}
|
|
} else {
|
|
_frame[i] = 2 + (_frameindex[i] > 18);
|
|
|
|
if (_frameindex[i] == 19)
|
|
_y[i] -= 4;
|
|
|
|
_y[i] += jump[_frameindex[i]++];
|
|
|
|
if (_frameindex[i] > 37)
|
|
_frameindex[i] = -2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EE::setwinner() {
|
|
if (_hits > 2) {
|
|
_winner = 1 - _hitter;
|
|
} else {
|
|
_winner = _tbx < 150 ? 1 : 0;
|
|
}
|
|
|
|
_tvely = abs(_bvely) >> 3;
|
|
_tvelx = abs(_bvelx) >> 3;
|
|
}
|
|
|
|
void EE::resetpt() {
|
|
_keymove[0][kDirUp] = 0;
|
|
_keymove[1][kDirUp] = 0;
|
|
getPos();
|
|
|
|
if (abs(_bvelx) > _tvelx) {
|
|
if (_bvelx < 0)
|
|
_bvelx = -_tvelx;
|
|
else
|
|
_bvelx = _tvelx;
|
|
}
|
|
|
|
if (abs(_bvely) > _tvely) {
|
|
if (_bvely < 0)
|
|
_bvely = -_tvely;
|
|
else
|
|
_bvely = _tvely;
|
|
}
|
|
|
|
docollisions();
|
|
moveball();
|
|
putshapes();
|
|
}
|
|
|
|
void EE::calcscore() {
|
|
if (_winner == _server) {
|
|
if (_soundEnabled && _mode != kModeMenu) {
|
|
playSound(kSndPoint);
|
|
}
|
|
_score[_winner]++;
|
|
if (_score[_winner] > 14 && _score[_winner] - _score[1 - _winner] > 1) {
|
|
init();
|
|
return;
|
|
}
|
|
} else {
|
|
if (_soundEnabled && _mode != kModeMenu) {
|
|
playSound(kSndLoss);
|
|
}
|
|
_server = _winner;
|
|
}
|
|
|
|
_bx = (_tbx = _pbx = (64 + _winner * 165)) << 6;
|
|
_by = (_tby = _pby = 135) << 6;
|
|
_bvelx = _bvely = _hits = _rebound[0] = _rebound[1] = 0;
|
|
_serve = _servevel = 1;
|
|
_hitter = 2;
|
|
_compserve = abs(_rnd) % 5;
|
|
if (_score[_server] == 14)
|
|
_compserve = 5;
|
|
_sstage = 0;
|
|
}
|
|
|
|
int EE::destination(int pl, int destx, int tol) {
|
|
int xp = _x[pl];
|
|
if (abs(xp - destx) < tol) {
|
|
_keymove[pl][kDirLeft] = 0;
|
|
_keymove[pl][kDirRight] = 0;
|
|
return 1;
|
|
}
|
|
if (xp < destx) {
|
|
_keymove[pl][kDirLeft] = 0;
|
|
_keymove[pl][kDirRight] = 2;
|
|
} else {
|
|
_keymove[pl][kDirLeft] = -2;
|
|
_keymove[pl][kDirRight] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int reset = false;
|
|
|
|
bool EE::moveball() {
|
|
if (!reset) {
|
|
_bx = 4096; _by = 8640; _bvelx = 125; _bvely = -259;
|
|
reset = true;
|
|
}
|
|
|
|
int rbvelx = _bvelx;
|
|
int rbvely = _bvely;
|
|
if (rbvelx > 319) rbvelx = 319;
|
|
if (rbvelx < -319) rbvelx = -319;
|
|
if (rbvely > 319) rbvely = 319;
|
|
if (rbvely < -319) rbvely = -319;
|
|
_pbx = _tbx;
|
|
_pby = _tby;
|
|
_bx += rbvelx;
|
|
_by += rbvely;
|
|
|
|
if (_bx < 320) {
|
|
_bx = 320;
|
|
rbvelx = -rbvelx;
|
|
rbvelx -= rbvelx >> 4;
|
|
rbvely -= rbvely >> 4;
|
|
if (_hitter == 1) {
|
|
_hitter = 2;
|
|
_hits = 0;
|
|
}
|
|
}
|
|
if (_bx > 18112) {
|
|
_bx = 18112;
|
|
rbvelx = -rbvelx;
|
|
rbvelx -= rbvelx >> 4;
|
|
rbvely -= rbvely >> 4;
|
|
if (_hitter == 0) {
|
|
_hitter = 2;
|
|
_hits = 0;
|
|
}
|
|
}
|
|
if (_by < 832) {
|
|
_by = 832;
|
|
rbvely = -rbvely;
|
|
rbvelx -= rbvelx >> 4;
|
|
rbvely -= rbvely >> 4;
|
|
}
|
|
bool hitfloor;
|
|
if (_by > 11392) {
|
|
_by = 11392;
|
|
rbvely = -rbvely;
|
|
hitfloor = false;
|
|
} else {
|
|
hitfloor = true;
|
|
}
|
|
|
|
//if (rbvely > 0) // Checked with original, this is how it is
|
|
// rbvely += 1;
|
|
//else
|
|
rbvely += 1;
|
|
|
|
_tbx = _bx >> 6;
|
|
_tby = _by >> 6;
|
|
_bvelx = rbvelx;
|
|
_bvely = rbvely;
|
|
|
|
return hitfloor;
|
|
}
|
|
|
|
void EE::docollisions() {
|
|
for (int i = 0; i < 2; i++) {
|
|
int dx = _tbx - _x[i] - i * 7;
|
|
int dy = (_tby - _y[i]) >> 1;
|
|
int dist = (dx >> 2) * dx + dy * dy;
|
|
if (dist < 110) {
|
|
int rndoff = 8 - (_rnd & 15);
|
|
if (_frameindex[i] > -1)
|
|
_bvely = -abs(_bvely) + (jump[_frameindex[i]] << (3 << _servevel));
|
|
else
|
|
_bvely = -abs(_bvely);
|
|
_bvely += rndoff;
|
|
_bvelx += dx * abs(dx) + ((_keymove[i][kDirRight] + _keymove[i][kDirLeft]) << (4 + _servevel)) + rndoff;
|
|
if (!_rebound[i]) {
|
|
if (_mode != kModeMenu) {
|
|
if (_soundEnabled && _mode != kModeMenu) {
|
|
playSound(kSndHit);
|
|
}
|
|
}
|
|
_bytop = 200;
|
|
_serve = 0;
|
|
_rebound[i] = 1;
|
|
if (_hitter != i) {
|
|
_hitter = i;
|
|
_hits = 0;
|
|
} else {
|
|
_hits++;
|
|
}
|
|
}
|
|
} else if (_rebound[i]) {
|
|
_rebound[i] = _servevel = 0;
|
|
}
|
|
}
|
|
|
|
int i = 1;
|
|
if (_tby > 91) {
|
|
if (_pbx < 128 && _tbx > 127) {
|
|
_bvelx = -abs(_bvelx) >> 1;
|
|
_bx = 127 * 64;
|
|
i = 0;
|
|
} else if (_pbx > 159 && _tbx < 160) {
|
|
_bvelx = abs(_bvelx) >> 1;
|
|
_bx = 160 * 64;
|
|
i = 0;
|
|
}
|
|
}
|
|
if (i && _tby > 81 && _tbx > 127 && _tbx < 160) {
|
|
if (_tby > 91) {
|
|
if (_tbx < 148)
|
|
_bvelx = -abs(_bvelx);
|
|
else
|
|
_bvelx = abs(_bvelx);
|
|
} else if ((_tbx > 147 && 161 - _tbx >= polecol[91 - _tby]) ||
|
|
(_tbx < 148 && _tbx - 133 >= polecol[91 - _tby])) {
|
|
if (_bvely > 0) {
|
|
int dx = _tbx - 145;
|
|
if (dx < -5) _bvelx = -abs(_bvelx);
|
|
if (dx > 5) _bvelx = abs(_bvelx);
|
|
_bvely = -abs(_bvely);
|
|
}
|
|
if (abs(_bvelx) > 32) _bvelx = _bvelx >> 1;
|
|
if (abs(_bvely) > 32) _bvely = _bvely >> 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void EE::computer0() {
|
|
_keymove[0][kDirUp] = 0;
|
|
if (_tby < _bytop) _bytop = _tby;
|
|
int rndoff = 5 - _rnd % 10;
|
|
int dest = 0;
|
|
if (_serve && ((_server & 1) == 0)) {
|
|
switch (_compserve) {
|
|
case 0:
|
|
dest = destination(0, 55, 2);
|
|
break;
|
|
case 1:
|
|
dest = destination(0, 84, 2);
|
|
break;
|
|
case 2:
|
|
dest = destination(0, 80, 2);
|
|
break;
|
|
case 3:
|
|
if (_sstage == 0) {
|
|
if ((dest = destination(0, 44, 2)))
|
|
_sstage = 1;
|
|
} else {
|
|
destination(0, 58, 2);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (_sstage == 0) {
|
|
if ((dest = destination(0, 90, 2)))
|
|
_sstage = 1;
|
|
} else {
|
|
destination(0, 58, 2);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (_sstage == 0) {
|
|
if (destination(0, 3, 2))
|
|
_sstage = 1;
|
|
dest = 0;
|
|
} else {
|
|
destination(0, 8 + _sstage++, 1);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
_keymove[0][kDirUp] = dest;
|
|
} else if (_bvely > 0 && _tbx < 140) {
|
|
int ystep, destx;
|
|
if (_bvely >> 6 == 0)
|
|
ystep = 0;
|
|
else
|
|
ystep = (140 - _tby) / (_bvely >> 6);
|
|
|
|
if (ystep < 1 || (_bvelx >> 6) == 0)
|
|
destx = _tbx;
|
|
else
|
|
destx = _tbx + (_bvelx >> 6) * ystep - 4;
|
|
|
|
int dx = _x[0] - _tbx;
|
|
|
|
if (abs(_bvelx) < 128 && _bytop < 75) {
|
|
if ((_tby < 158) ^ (_bvelx < 0))
|
|
destination(0, _tbx - 15, 3);
|
|
else
|
|
destination(0, _tbx + 15, 3);
|
|
} else {
|
|
if (_tby > 130) {
|
|
if (abs(dx) > 6 && abs(_bvelx) < 1024) {
|
|
destination(0, _tbx - ((_x[0] - 60) >> 3), 3);
|
|
} else {
|
|
destination(0, _tbx + rndoff + ((_x[0] - 60) >> 3), 10);
|
|
_keymove[0][kDirUp] = _x[0] < 105 && (_hitter != 0 || _hits < 2);
|
|
}
|
|
} else {
|
|
if (destx < 3)
|
|
destx = 6 - destx;
|
|
if (destx > 123)
|
|
destx = 246 - destx;
|
|
destination(0, destx + rndoff, 3);
|
|
}
|
|
}
|
|
} else
|
|
destination(0, 56, 8);
|
|
}
|
|
|
|
void EE::computer1() {
|
|
_keymove[1][kDirUp] = 0;
|
|
if (_tby < _bytop) _bytop = _tby;
|
|
int rndoff = 5 - _rnd % 10;
|
|
if (_serve && ((_server & 1) == 1)) {
|
|
int dest = 0;
|
|
switch (_compserve) {
|
|
case 0:
|
|
dest = destination(1, 232, 2);
|
|
break;
|
|
case 1:
|
|
dest = destination(1, 202, 2);
|
|
break;
|
|
case 2:
|
|
dest = destination(1, 208, 2);
|
|
break;
|
|
case 3:
|
|
if (_sstage == 0) {
|
|
if ((dest = destination(1, 250, 2)))
|
|
_sstage = 1;
|
|
} else {
|
|
destination(1, 220, 2);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (_sstage == 0) {
|
|
if ((dest = destination(1, 190, 2)))
|
|
_sstage = 1;
|
|
} else {
|
|
destination(1, 230, 2);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (_sstage == 0) {
|
|
if (destination(1, 277, 2))
|
|
_sstage = 1;
|
|
dest = 0;
|
|
} else {
|
|
destination(1, 272 - _sstage++, 1);
|
|
dest = 1;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
_keymove[1][kDirUp] = dest;
|
|
} else if (_bvely > 0 && _tbx > 125) {
|
|
int ystep, destx;
|
|
if (_bvely >> 6 == 0)
|
|
ystep = 0;
|
|
else
|
|
ystep = (140 - _tby) / (_bvely >> 6);
|
|
|
|
if (ystep < 1 || (_bvelx >> 6) == 0)
|
|
destx = _tbx;
|
|
else
|
|
destx = _tbx + (_bvelx >> 6) * ystep - 4;
|
|
|
|
int dx = _x[1] - _tbx;
|
|
|
|
if (abs(_bvelx) < 128 && _bytop < 75) {
|
|
if ((_tby < 158) ^ (_bvelx < 0))
|
|
destination(1, _tbx + 15, 3);
|
|
else
|
|
destination(1, _tbx - 15, 3);
|
|
} else {
|
|
if (_tby > 130) {
|
|
if (abs(dx) > 6 && abs(_bvelx) < 1024)
|
|
destination(1, _tbx + ((_x[1] - 218) >> 3), 3);
|
|
else {
|
|
destination(1, _tbx - rndoff - ((_x[1] - 218) >> 3), 10);
|
|
_keymove[1][kDirUp] = _x[1] > 175 && (_hitter != 1 || _hits < 2);
|
|
}
|
|
} else {
|
|
if (destx < 158)
|
|
destx = 316 - destx;
|
|
if (destx > 277)
|
|
destx = 554 - destx;
|
|
destination(1, destx - rndoff, 3);
|
|
}
|
|
}
|
|
} else
|
|
destination(1, 211, 8);
|
|
}
|
|
|
|
void EE::init() {
|
|
_rnd = 0;
|
|
_starter = _winner = _hits = 0;
|
|
_bvelx = _bvely = 0;
|
|
_tbx = 200; _tby = 20;
|
|
_bytop = 200;
|
|
_x[0] = 64; _x[1] = 226;
|
|
|
|
_air = false;
|
|
|
|
_rcnt = 0;
|
|
_tvelx = _tvely = 0;
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
_px[i] = _x[i];
|
|
_y[i] = 173;
|
|
_frameindex[i] = -1;
|
|
_rebound[i] = 0;
|
|
_score[i] = 0;
|
|
_keymove[i][kDirRight] = _keymove[i][kDirLeft] = _keymove[i][kDirUp] = 0;
|
|
_frame[i] = 0;
|
|
}
|
|
|
|
_oCoords = false;
|
|
_opts = 3;
|
|
_opt = 0;
|
|
|
|
_mode = kModeMenu;
|
|
_soundEnabled = false;
|
|
|
|
_olx = _oly = _orx = _ory = _obx = _oby = 0;
|
|
_compserve = 0;
|
|
_sstage = 0;
|
|
|
|
_tbx = 64 + _starter * 165;
|
|
_pbx = _tbx;
|
|
_bx = _tbx << 6;
|
|
_tby = 135;
|
|
_pby = 135;
|
|
_by = _tby << 6;
|
|
|
|
_server = 2 + _starter;
|
|
_hitter = 2;
|
|
_serve = _servevel = 1;
|
|
|
|
_rmode = false;
|
|
|
|
_shouldQuit = false;
|
|
|
|
_inited = true;
|
|
}
|
|
|
|
void EE::draw(int sn, int x1, int y1) {
|
|
int x = x1 * _scale;
|
|
int y = y1 * _scale;
|
|
|
|
_back.copyRectToSurfaceWithKey(_sp[sn].getPixels(), _sp[sn].pitch, x, y, _sp[sn].w, _sp[sn].h, _colorKey);
|
|
g_system->copyRectToOverlay(_back.getBasePtr(x, y), _back.pitch, _windowX + x, _windowY + y, _sp[sn].w, _sp[sn].h);
|
|
}
|
|
|
|
void EE::putshapes() {
|
|
int sprite;
|
|
|
|
cls(false);
|
|
|
|
if (_oCoords) {
|
|
int obx = _obx * _scale, oby = _oby * _scale;
|
|
int olx = _olx * _scale, oly = _oly * _scale;
|
|
int orx = _orx * _scale, ory = _ory * _scale;
|
|
g_system->copyRectToOverlay(_back.getBasePtr(obx, oby), _back.pitch, _windowX + obx, _windowY + oby, _sp[kSpB1].w, _sp[kSpB1].h);
|
|
g_system->copyRectToOverlay(_back.getBasePtr(olx, oly), _back.pitch, _windowX + olx, _windowY + oly, _sp[kSpL1].w, _sp[kSpL1].h);
|
|
g_system->copyRectToOverlay(_back.getBasePtr(orx, ory), _back.pitch, _windowX + orx, _windowY + ory, _sp[kSpR1].w, _sp[kSpR1].h);
|
|
}
|
|
|
|
sprite = kSpB1 + (_tbx / 16) % 4;
|
|
draw(sprite, _tbx, _tby);
|
|
_obx = _tbx;
|
|
_oby = _tby;
|
|
|
|
if (_y[0] < 173) {
|
|
sprite = kSpL3;
|
|
} else {
|
|
if ((_x[0] / 8) % 2)
|
|
sprite = kSpL1;
|
|
else
|
|
sprite = kSpL2;
|
|
}
|
|
draw(sprite, _x[0], _y[0]);
|
|
_olx = _x[0];
|
|
_oly = _y[0];
|
|
|
|
if (_y[1] < 173) {
|
|
sprite = kSpR3;
|
|
} else {
|
|
if ((_x[1] / 8) % 2)
|
|
sprite = kSpR1;
|
|
else
|
|
sprite = kSpR2;
|
|
}
|
|
draw(sprite, _x[1], _y[1]);
|
|
_orx = _x[1];
|
|
_ory = _y[1];
|
|
|
|
_oCoords = true;
|
|
|
|
const int frames[] = {
|
|
153, 106, 160, 200,
|
|
4, 13, 6, 200,
|
|
310, 13, 312, 200,
|
|
4, 13, 312, 14,
|
|
4, 199, 312, 200,
|
|
154, 107, 159, 199
|
|
};
|
|
|
|
uint32 color1 = _back.format.RGBToColor(5 * 16, 7 * 16, 8 * 16);
|
|
uint32 color2 = _back.format.RGBToColor(6 * 16, 8 * 16, 12 * 16);
|
|
|
|
const int *ptr = frames;
|
|
for (int i = 0; i < 6; i++, ptr += 4) {
|
|
Common::Rect r(ptr[0] * _scale, ptr[1] * _scale, ptr[2] * _scale, ptr[3] * _scale);
|
|
_back.fillRect(r, (i < 5 ? color1 : color2));
|
|
g_system->copyRectToOverlay(_back.getBasePtr(r.left, r.top), _back.pitch, _windowX + r.left, _windowY + r.top, r.width(), r.height());
|
|
}
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
int startx = i ? 264 : 32;
|
|
|
|
draw(kSpNum0 + _score[i] / 10, startx, 1);
|
|
startx += 8;
|
|
draw(kSpNum0 + _score[i] % 10, startx, 1);
|
|
startx += 8;
|
|
draw(_server == i ? kSpStar : kSpSpace, startx, 1);
|
|
}
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
int sx = i == 0 ? 92 : 80;
|
|
int sy = i == 0 ? 2 : 20;
|
|
|
|
int code = i == 0 ? kSpCode1 : i - 1 == _opt ? kSpCode1h + i : kSpCode1 + i;
|
|
draw(code, sx, sy + i * 10);
|
|
|
|
if (_mode != kModeMenu)
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EE::doMenu(Common::Event &e) {
|
|
switch (e.kbd.keycode) {
|
|
case Common::KEYCODE_UP:
|
|
_opt--;
|
|
if (_opt < 0)
|
|
_opt = 4;
|
|
break;
|
|
|
|
case Common::KEYCODE_DOWN:
|
|
_opt = (_opt + 1) % 5;
|
|
break;
|
|
|
|
case Common::KEYCODE_RETURN:
|
|
if (_opt < 4) {
|
|
_opts = _opt;
|
|
_mode = kModePlay;
|
|
|
|
cls();
|
|
} else {
|
|
_shouldQuit = true;
|
|
}
|
|
break;
|
|
|
|
case Common::KEYCODE_ESCAPE:
|
|
_shouldQuit = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void EE::game() {
|
|
if (_mode == kModePlay || _mode == kModeMenu) {
|
|
_rnd = (_rnd * 5 + 1) % 32767;
|
|
|
|
if (_opts & 1)
|
|
computer0();
|
|
if (_opts & 2)
|
|
computer1();
|
|
if (_rmode) {
|
|
if (_rcnt-- > 0 || _frameindex[0] != -1 || _frameindex[1] != -1) {
|
|
resetpt();
|
|
} else {
|
|
_rmode = false;
|
|
calcscore();
|
|
}
|
|
return;
|
|
}
|
|
|
|
getPos();
|
|
|
|
if (_serve) {
|
|
docollisions();
|
|
_air = true;
|
|
} else {
|
|
if (_air) {
|
|
docollisions();
|
|
_air = moveball();
|
|
}
|
|
}
|
|
if (!_air || _hits > 2) {
|
|
setwinner();
|
|
_rmode = true;
|
|
_rcnt = 20;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EE::playSound(int sound) {
|
|
// FIXME
|
|
}
|
|
|
|
static const uint32 ball[21] = {
|
|
0x0000fd00, 0x00074ac0, 0x000afde0, 0x001703e8, 0x0038f7d8, 0x0056f73c,
|
|
0x00aef6fc, 0x00cf79fb, 0x01afbbf7, 0x01b7bdcd, 0x0077dd3a, 0x013beef3,
|
|
0x01bbef6a, 0x015df78b, 0x00defbea, 0x00ef7dd8, 0x00779eb4, 0x0029ef68,
|
|
0x001ef4a0, 0x000673c0, 0x0000ae00
|
|
};
|
|
|
|
static const uint32 head[38] = {
|
|
0xbb400000, 0x0000000f, 0xea650000, 0x000003af, 0xfaaa6000, 0x00000e7f,
|
|
0xfea5a400, 0x03ff2af0, 0x3eaa6900, 0x3ea969c0, 0x3ea99940, 0xeaaa69c8,
|
|
0x3a669540, 0xea995540, 0x5a555550, 0xa9aa999a, 0x65a65550, 0x2aa69a5a,
|
|
0x59555650, 0x02aaaa55, 0x6aa66550, 0x000aa950, 0x6a569950, 0x000a9500,
|
|
0xa9595580, 0x00015001, 0xa9a55540, 0x00000015, 0xa9a9a500, 0x0000015a,
|
|
0x59695800, 0x00001659, 0x65659000, 0x00000a96, 0xa65a8000, 0x000002aa,
|
|
0xa6500000, 0x0000002a
|
|
};
|
|
|
|
static const uint32 legs[42] = {
|
|
0xa0000000, 0x00000000, 0x80000000, 0x00000002, 0x80000000, 0x00000002, 0xa0000000,
|
|
0x00000000, 0x50000000, 0x00000000, 0xf0000000, 0x00000003, 0xfc000000, 0x000003ff,
|
|
|
|
0xa0000000, 0x00000002, 0x0a000000, 0x0000000a, 0x02400000, 0x00000028, 0x00700000,
|
|
0x00000028, 0x00fc0000, 0x00000014, 0x03c00000, 0x000000fc, 0x0f000000, 0x0000ffff,
|
|
|
|
0xa0000000, 0x00000000, 0x80000000, 0x00000002, 0xa8000000, 0x00000002, 0x29c00000,
|
|
0x00000000, 0x01f00000, 0x00000000, 0x0fc00000, 0x00000000, 0xfc000000, 0x00000000
|
|
};
|
|
|
|
static const int spcolors[10 * 3] = {
|
|
0, 0, 0, 8, 15, 8, 6, 12, 6, 12, 13, 12,
|
|
0, 0, 0, 15, 8, 8, 12, 6, 6, 13, 12, 12,
|
|
0, 0, 0, 12, 12, 12
|
|
};
|
|
|
|
const char *const codes =
|
|
"Dvhgkm#Ztrsm|ffrs(#$%&'#$%&O}pes&}{1$M{tiq$%&'#$M{tiq${y5(Fsrv||hv%&'#$"
|
|
"Hutxxxjx'~v2%N|udr%&'#Gtsw}wiw&}{1$Hutxxxjx'#$%&'(#$%W|qw$%&'(#$%&'";
|
|
|
|
void EE::setupGraphics() {
|
|
// Determine scale factor
|
|
float scaleX = g_system->getOverlayWidth() * 0.9 / 320;
|
|
float scaleY = g_system->getOverlayHeight() * 0.9 / 200;
|
|
_scale = MIN(scaleX, scaleY);
|
|
|
|
_windowW = 320 * _scale;
|
|
_windowH = 200 * _scale;
|
|
_windowX = (g_system->getOverlayWidth() > 320) ? (g_system->getOverlayWidth() - _windowW) / 2 : 0;
|
|
_windowY = (g_system->getOverlayHeight() > 200) ? (g_system->getOverlayHeight() - _windowH) / 2 : 0;
|
|
|
|
_format = g_system->getOverlayFormat();
|
|
_back.create(_windowW, _windowH, _format);
|
|
|
|
_colorBlack = _format.RGBToColor( 0 * 16, 0 * 16, 0 * 16);
|
|
_colorBlue = _format.RGBToColor( 5 * 16, 7 * 16, 8 * 16);
|
|
_colorOrange = _format.RGBToColor(15 * 16, 7 * 16, 8 * 16);
|
|
_colorKey = _colorBlack;
|
|
|
|
cls();
|
|
|
|
uint32 palette[12];
|
|
for (int i = 0; i < 10 * 3; i += 3)
|
|
palette[i / 3] = _back.format.RGBToColor(spcolors[i] * 16, spcolors[i + 1] * 16, spcolors[i + 2] * 16);
|
|
|
|
Graphics::Surface tmp;
|
|
int w = 25, h = 21;
|
|
tmp.create(w, h, g_system->getOverlayFormat());
|
|
|
|
for (int s = 0; s < 4; s++) {
|
|
|
|
int posy = 0, dy = 1;
|
|
if (s & 2) { posy = 20; dy = -1; }
|
|
|
|
for (int y = 0; y < h; y++, posy += dy) {
|
|
uint32 pixels = ball[y];
|
|
|
|
int posx = 0, dx = 1;
|
|
if (s & 1) { posx = 24; dx = -1; }
|
|
|
|
for (int x = 0; x < w; x++, posx += dx) {
|
|
int color = pixels & 1;
|
|
|
|
pixels >>= 1;
|
|
|
|
tmp.setPixel(posx, posy, palette[color + 8]);
|
|
}
|
|
}
|
|
|
|
Graphics::Surface *tmp2 = tmp.scale(w * _scale, h * _scale);
|
|
_sp[kSpB1 + s].copyFrom(*tmp2);
|
|
tmp2->free();
|
|
delete tmp2;
|
|
}
|
|
tmp.free();
|
|
|
|
w = 32;
|
|
h = 26;
|
|
tmp.create(w, h, g_system->getOverlayFormat());
|
|
|
|
for (int s = 0; s < 6; s++) {
|
|
for (int y = 0; y < h; y++) {
|
|
const uint32 *ptr = (y < 19) ? &head[y * 2] : &legs[(y - 19 + (s % 3) * 7) * 2];
|
|
uint32 pixels = *ptr++;
|
|
|
|
int posx = 0, dx = 1;
|
|
if (s > 2) { posx = 31; dx = -1; }
|
|
|
|
for (int x = 0; x < w; x++, posx += dx) {
|
|
int color = pixels & 3;
|
|
|
|
pixels >>= 2;
|
|
|
|
if (x == 15)
|
|
pixels = *ptr;
|
|
|
|
tmp.setPixel(posx, y, palette[color + 4 * (s / 3)]);
|
|
}
|
|
}
|
|
|
|
Graphics::Surface *tmp2 = tmp.scale(w * _scale, h * _scale);
|
|
_sp[kSpL1 + s].copyFrom(*tmp2);
|
|
tmp2->free();
|
|
delete tmp2;
|
|
}
|
|
tmp.free();
|
|
|
|
w = 23 * 8;
|
|
h = 10;
|
|
tmp.create(w, h, g_system->getOverlayFormat());
|
|
for (int hl = 0; hl < 2; hl++) {
|
|
for (int i = 0; i < 6; i++) {
|
|
tmp.fillRect(Common::Rect(0, 0, w, h), hl == 1 ? _colorBlue : _colorKey);
|
|
|
|
char buf[100];
|
|
int c;
|
|
for (c = 0; c < 23; c++)
|
|
buf[c] = codes[c + 23 * i] - 3 - c % 6;
|
|
buf[c] = 0;
|
|
|
|
int c1 = i == 0 ? _colorOrange : hl == 1 ? _colorKey : _colorBlue;
|
|
|
|
_font.drawString(&tmp, buf, 0, 1, w, c1, Graphics::kTextAlignLeft, 0, false);
|
|
|
|
Graphics::Surface *tmp2 = tmp.scale(w * _scale, h * _scale, true);
|
|
_sp[kSpCode1 + hl * 6 + i].copyFrom(*tmp2);
|
|
tmp2->free();
|
|
delete tmp2;
|
|
}
|
|
}
|
|
tmp.free();
|
|
|
|
w = 8;
|
|
h = 10;
|
|
tmp.create(w, h, g_system->getOverlayFormat());
|
|
for (int i = 0; i < 12; i++) {
|
|
tmp.fillRect(Common::Rect(0, 0, w, h), _colorKey);
|
|
|
|
char buf[2];
|
|
buf[0] = i == 10 ? '*' : i == 11 ? ' ' : '0' + i;
|
|
buf[1] = 0;
|
|
|
|
int c = i > 9 ? _colorBlue : _colorOrange;
|
|
|
|
_font.drawString(&tmp, buf, 0, 1, w, c, Graphics::kTextAlignLeft, 0, false);
|
|
|
|
Graphics::Surface *tmp2 = tmp.scale(w * _scale, h * _scale, true);
|
|
_sp[kSpNum0 + i].copyFrom(*tmp2);
|
|
tmp2->free();
|
|
delete tmp2;
|
|
}
|
|
tmp.free();
|
|
}
|
|
|
|
} // End of namespace GUI
|