Initial commit
This commit is contained in:
282
engines/ultima/ultima8/gfx/anim_dat.cpp
Normal file
282
engines/ultima/ultima8/gfx/anim_dat.cpp
Normal file
@@ -0,0 +1,282 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/anim_dat.h"
|
||||
|
||||
#include "ultima/ultima8/world/actors/actor_anim.h"
|
||||
#include "ultima/ultima8/world/actors/actor.h"
|
||||
#include "ultima/ultima8/world/get_object.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
AnimDat::AnimDat() {
|
||||
}
|
||||
|
||||
AnimDat::~AnimDat() {
|
||||
for (unsigned int i = 0; i < _anims.size(); i++)
|
||||
delete _anims[i];
|
||||
}
|
||||
|
||||
const ActorAnim *AnimDat::getAnim(uint32 shape) const {
|
||||
if (shape >= _anims.size())
|
||||
return nullptr;
|
||||
|
||||
return _anims[shape];
|
||||
}
|
||||
|
||||
const AnimAction *AnimDat::getAnim(uint32 shape, uint32 action) const {
|
||||
if (shape >= _anims.size())
|
||||
return nullptr;
|
||||
if (_anims[shape] == 0)
|
||||
return nullptr;
|
||||
|
||||
return _anims[shape]->getAction(action);
|
||||
}
|
||||
|
||||
uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Actor *actor) {
|
||||
if (GAME_IS_U8) {
|
||||
return static_cast<uint32>(action);
|
||||
} else {
|
||||
bool smallwpn = true;
|
||||
bool altfire = false;
|
||||
bool isavatar = (actor && actor->getShape() == 1);
|
||||
if (isavatar && actor->getActiveWeapon()) {
|
||||
const Item *wpn = getItem(actor->getActiveWeapon());
|
||||
const ShapeInfo *shapeinfo = (wpn ? wpn->getShapeInfo() : nullptr);
|
||||
const WeaponInfo *wpninfo = (shapeinfo ? shapeinfo->_weaponInfo : nullptr);
|
||||
smallwpn = (wpninfo && wpninfo->_small);
|
||||
altfire = (wpninfo && (wpninfo->_overlayShape == 0x36e || wpninfo->_overlayShape == 0x33b));
|
||||
}
|
||||
|
||||
//
|
||||
// For crusader the actions have different IDs. Rather than
|
||||
// rewrite everything, we just translate them here for all the ones
|
||||
// we want to use programmatically. There are more, but they are
|
||||
// called from usecode so don't need translation.
|
||||
//
|
||||
// We also translate based on weapon. See the function at 1128:2104
|
||||
//
|
||||
// First, if the animation includes the Animation::crusaderAbsoluteAnimFlag
|
||||
// bitmask then it's from the usecode - use directly and don't translate.
|
||||
//
|
||||
const uint32 action_int = static_cast<uint32>(action);
|
||||
if (action_int & Animation::crusaderAbsoluteAnimFlag)
|
||||
return action_int - Animation::crusaderAbsoluteAnimFlag;
|
||||
|
||||
switch (action) {
|
||||
case Animation::stand:
|
||||
return Animation::standCru;
|
||||
case Animation::step:
|
||||
return Animation::walkCru; // Same as walk in crusader.
|
||||
case Animation::walk:
|
||||
return Animation::walkCru;
|
||||
case Animation::retreat:
|
||||
return (smallwpn ? Animation::retreatSmallWeapon : Animation::retreatLargeWeapon);
|
||||
case Animation::reloadSmallWeapon:
|
||||
return (smallwpn ? Animation::reloadSmallWeapon : Animation::reloadLargeWeapon);
|
||||
case Animation::run:
|
||||
return Animation::runCru;
|
||||
case Animation::combatRunSmallWeapon:
|
||||
return (smallwpn ? Animation::combatRunSmallWeapon : Animation::combatRunLargeWeapon);
|
||||
case Animation::combatStand:
|
||||
return (smallwpn ? Animation::combatStandSmallWeapon : Animation::combatStandLargeWeapon);
|
||||
case Animation::unreadyWeapon:
|
||||
return (smallwpn ? Animation::unreadySmallWeapon : Animation::unreadyLargeWeapon);
|
||||
case Animation::readyWeapon:
|
||||
return (smallwpn ? Animation::readySmallWeapon : Animation::readyLargeWeapon);
|
||||
case Animation::attack: {
|
||||
if (smallwpn)
|
||||
return Animation::fireSmallWeapon;
|
||||
return (altfire ? Animation::brightFireLargeWpn : Animation::fireLargeWeapon);
|
||||
}
|
||||
// Note: 14, 17, 21, 22, 29 == nothing for avatar
|
||||
case Animation::fallBackwards:
|
||||
return Animation::fallBackwardsCru;
|
||||
case Animation::die:
|
||||
return Animation::fallBackwardsCru; // by default fall over backwards.
|
||||
case Animation::advance:
|
||||
return (smallwpn ? Animation::advanceSmallWeapon : Animation::advanceLargeWeapon);
|
||||
// Kneel start/end never used in code - mover process uses correct ones.
|
||||
/*case Animation::startKneeling:
|
||||
return Animation::kneelStartCru;
|
||||
case Animation::stopKneeling:
|
||||
return Animation::kneelEndCru;*/
|
||||
case Animation::kneel:
|
||||
return (smallwpn ? Animation::kneelingWithSmallWeapon : Animation::kneelingWithLargeWeapon);
|
||||
case Animation::kneelAndFire: {
|
||||
if (smallwpn)
|
||||
return Animation::kneelAndFireSmallWeapon;
|
||||
return (altfire ? Animation::brightKneelAndFireLargeWeapon : Animation::kneelAndFireLargeWeapon);
|
||||
}
|
||||
case Animation::lookLeft:
|
||||
return 0;
|
||||
case Animation::lookRight:
|
||||
return 0;
|
||||
case Animation::jump:
|
||||
return Animation::quickJumpCru;
|
||||
//case Animation::startRunLargeWeapon:
|
||||
// return (smallwpn ? Animation::startRunSmallWeapon : Animation::startRunLargeWeapon); // FIXME: overlaps with kneel
|
||||
case Animation::stopRunningAndDrawSmallWeapon:
|
||||
return (smallwpn ? Animation::stopRunningAndDrawSmallWeapon : Animation::stopRunningAndDrawLargeWeapon);
|
||||
default:
|
||||
return action_int;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimDat::load(Common::SeekableReadStream *rs) {
|
||||
AnimFrame f;
|
||||
|
||||
// CONSTANT !
|
||||
_anims.resize(2048);
|
||||
|
||||
unsigned int actioncount = 64;
|
||||
|
||||
if (GAME_IS_CRUSADER) {
|
||||
actioncount = 256;
|
||||
}
|
||||
|
||||
for (unsigned int shape = 0; shape < _anims.size(); shape++) {
|
||||
rs->seek(4 * shape);
|
||||
uint32 offset = rs->readUint32LE();
|
||||
|
||||
if (offset == 0) {
|
||||
_anims[shape] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
ActorAnim *a = new ActorAnim();
|
||||
|
||||
// CONSTANT !
|
||||
a->_actions.resize(actioncount);
|
||||
|
||||
for (unsigned int action = 0; action < actioncount; action++) {
|
||||
rs->seek(offset + action * 4);
|
||||
uint32 actionoffset = rs->readUint32LE();
|
||||
|
||||
if (actionoffset == 0) {
|
||||
a->_actions[action] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
a->_actions[action] = new AnimAction();
|
||||
|
||||
a->_actions[action]->_shapeNum = shape;
|
||||
a->_actions[action]->_action = action;
|
||||
|
||||
rs->seek(actionoffset);
|
||||
// byte 0: action size
|
||||
uint32 actionsize = rs->readByte();
|
||||
a->_actions[action]->_size = actionsize;
|
||||
// byte 1: flags low byte
|
||||
uint32 rawflags = rs->readByte();
|
||||
// byte 2: frame repeat and rotated flag
|
||||
byte repeatAndRotateFlag = rs->readByte();
|
||||
a->_actions[action]->_frameRepeat = repeatAndRotateFlag & 0xf;
|
||||
if (GAME_IS_U8 && (repeatAndRotateFlag & 0xf0)) {
|
||||
// This should never happen..
|
||||
error("Anim data: frame repeat byte should never be > 0xf");
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
// WORKAROUND: In Crusader, the process wait semantics changed so
|
||||
// wait of 1 frame was the same as no wait. The frame repeat
|
||||
// is implemented as a process wait, so this effectively reduced
|
||||
// all frame repeats by 1.
|
||||
if (a->_actions[action]->_frameRepeat)
|
||||
a->_actions[action]->_frameRepeat--;
|
||||
}
|
||||
// byte 3: flags high byte
|
||||
rawflags |= rs->readByte() << 8;
|
||||
|
||||
// Only one flag in this byte in crusader.. the "rotate" flag.
|
||||
rawflags |= (repeatAndRotateFlag & 0xf0) << 12;
|
||||
|
||||
a->_actions[action]->_flags = AnimAction::loadAnimActionFlags(rawflags);
|
||||
|
||||
unsigned int dirCount = 8;
|
||||
if (a->_actions[action]->hasFlags(AnimAction::AAF_16DIRS)) {
|
||||
dirCount = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
if (a->_actions[action]->_flags & AnimAction::AAF_UNKFLAGS) {
|
||||
warning("AnimFlags: shape %d action %d has unknown flags %04X", shape, action,
|
||||
a->_actions[action]->_flags & AnimAction::AAF_UNKFLAGS);
|
||||
}
|
||||
*/
|
||||
|
||||
a->_actions[action]->_dirCount = dirCount;
|
||||
|
||||
for (unsigned int dir = 0; dir < dirCount; dir++) {
|
||||
a->_actions[action]->_frames[dir].clear();
|
||||
|
||||
for (unsigned int j = 0; j < actionsize; j++) {
|
||||
if (GAME_IS_U8) {
|
||||
f._frame = rs->readByte(); // & 0x7FF;
|
||||
uint8 x = rs->readByte();
|
||||
f._frame += (x & 0x7) << 8;
|
||||
f._deltaZ = rs->readSByte();
|
||||
f._sfx = rs->readByte();
|
||||
f._deltaDir = rs->readSByte();
|
||||
f._flags = rs->readByte();
|
||||
f._flags += (x & 0xF8) << 8;
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
// byte 0: low byte of frame
|
||||
f._frame = rs->readByte();
|
||||
// byte 1: low nibble is high part of frame, high nibble is flags (used later)
|
||||
const uint8 x = rs->readByte();
|
||||
f._frame += (x & 0xF) << 8;
|
||||
// byte 2: delta z
|
||||
f._deltaZ = rs->readSByte();
|
||||
// byte 3: sfx
|
||||
f._sfx = rs->readByte();
|
||||
// byte 4: deltadir (signed) - convert to pixels
|
||||
f._deltaDir = rs->readSByte();
|
||||
// byte 5: flags. The lowest bit is actually a sign bit for
|
||||
// deltaDir, which is technically 9 bits long. There are no
|
||||
// animations in the game exceeding 8-bit signed, the 9th bit
|
||||
// is there so that multiple frames can be stacked in the same
|
||||
// struct by the original game when it's skipping frames.
|
||||
// We have more memory and don't frame-skip, so just ignore it.
|
||||
f._flags = rs->readByte() & 0xFE;
|
||||
f._flags += (x & 0xF0) << 8;
|
||||
// bytes 6, 7: more flags
|
||||
f._flags += rs->readUint16LE() << 16;
|
||||
|
||||
/*if (f._flags & AnimFrame::AFF_UNKNOWN) {
|
||||
warning("AnimFlags: shape %d action %d dir %d frame %d has unknown flags %08X", shape, action, dir, j,
|
||||
f._flags & AnimFrame::AFF_UNKNOWN);
|
||||
}*/
|
||||
}
|
||||
a->_actions[action]->_frames[dir].push_back(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_anims[shape] = a;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
54
engines/ultima/ultima8/gfx/anim_dat.h
Normal file
54
engines/ultima/ultima8/gfx/anim_dat.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_ANIMDAT_H
|
||||
#define ULTIMA8_GFX_ANIMDAT_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/world/actors/animation.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class AnimAction;
|
||||
class ActorAnim;
|
||||
class Actor;
|
||||
|
||||
class AnimDat {
|
||||
public:
|
||||
AnimDat();
|
||||
~AnimDat();
|
||||
|
||||
void load(Common::SeekableReadStream *rs);
|
||||
|
||||
const ActorAnim *getAnim(uint32 shape) const;
|
||||
const AnimAction *getAnim(uint32 shape, uint32 action) const;
|
||||
|
||||
//! Return the action number for a given animation sequence on the given actor
|
||||
static uint32 getActionNumberForSequence(Animation::Sequence action, const Actor *actor);
|
||||
private:
|
||||
Std::vector<ActorAnim *> _anims;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
142
engines/ultima/ultima8/gfx/avi_player.cpp
Normal file
142
engines/ultima/ultima8/gfx/avi_player.cpp
Normal file
@@ -0,0 +1,142 @@
|
||||
/* 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 "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/gfx/avi_player.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "video/avi_decoder.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
AVIPlayer::AVIPlayer(Common::SeekableReadStream *rs, int width, int height, const byte *overridePal, bool noScale)
|
||||
: MoviePlayer(), _playing(false), _width(width), _height(height),
|
||||
_doubleSize(false), _pausedMusic(false), _overridePal(overridePal) {
|
||||
_decoder = new Video::AVIDecoder();
|
||||
_decoder->loadStream(rs);
|
||||
uint32 vidWidth = _decoder->getWidth();
|
||||
uint32 vidHeight = _decoder->getHeight();
|
||||
if (vidWidth <= _width / 2 && vidHeight <= _height / 2 && !noScale) {
|
||||
_doubleSize = true;
|
||||
vidHeight *= 2;
|
||||
vidWidth *= 2;
|
||||
}
|
||||
_xoff = _width / 2 - (vidWidth / 2);
|
||||
_yoff = _height / 2 - (vidHeight / 2);
|
||||
_currentFrame.create(vidWidth, vidHeight, _decoder->getPixelFormat());
|
||||
_currentFrame.fillRect(Common::Rect(0, 0, vidWidth, vidHeight),
|
||||
_decoder->getPixelFormat().RGBToColor(0, 0, 0));
|
||||
if (_currentFrame.format.bytesPerPixel == 1)
|
||||
_currentFrame.setTransparentColor(0);
|
||||
}
|
||||
|
||||
AVIPlayer::~AVIPlayer() {
|
||||
delete _decoder;
|
||||
}
|
||||
|
||||
void AVIPlayer::start() {
|
||||
MusicProcess *music = MusicProcess::get_instance();
|
||||
if (music && music->isPlaying()) {
|
||||
music->pauseMusic();
|
||||
_pausedMusic = true;
|
||||
}
|
||||
|
||||
_playing = true;
|
||||
_decoder->start();
|
||||
}
|
||||
|
||||
void AVIPlayer::stop() {
|
||||
MusicProcess *music = MusicProcess::get_instance();
|
||||
if (music && _pausedMusic) {
|
||||
music->unpauseMusic();
|
||||
_pausedMusic = false;
|
||||
}
|
||||
|
||||
_playing = false;
|
||||
_decoder->stop();
|
||||
}
|
||||
|
||||
void AVIPlayer::paint(RenderSurface *surf, int /*lerp*/) {
|
||||
if (_decoder->endOfVideo()) {
|
||||
_playing = false;
|
||||
return;
|
||||
}
|
||||
if (_decoder->needsUpdate())
|
||||
{
|
||||
const Graphics::Surface *frame = _decoder->decodeNextFrame();
|
||||
if (!frame || _decoder->getCurFrame() < 0) {
|
||||
// Some sort of decoding error?
|
||||
_playing = false;
|
||||
return;
|
||||
}
|
||||
if (frame->format.bytesPerPixel == 1) {
|
||||
const byte *pal;
|
||||
if (_overridePal)
|
||||
pal = _overridePal;
|
||||
else
|
||||
pal = _decoder->getPalette();
|
||||
|
||||
_currentFrame.setPalette(pal, 0, 256);
|
||||
}
|
||||
if (_doubleSize) {
|
||||
// TODO: Add support for multiple bytes per pixel
|
||||
assert(_currentFrame.w == frame->w * 2 && _currentFrame.h == frame->h * 2);
|
||||
const int bpp = frame->format.bytesPerPixel;
|
||||
for (int y = 0; y < frame->h; y++) {
|
||||
const uint8 *srcPixel = static_cast<const uint8 *>(frame->getPixels()) + frame->pitch * y;
|
||||
uint8 *dstPixels = static_cast<uint8 *>(_currentFrame.getPixels()) + _currentFrame.pitch * y * 2;
|
||||
for (int x = 0; x < frame->w; x++) {
|
||||
for (int i = 0; i < bpp; i++) {
|
||||
dstPixels[x * 2 * bpp + i] = *srcPixel;
|
||||
dstPixels[x * 2 * bpp + i + bpp] = *srcPixel;
|
||||
srcPixel++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_currentFrame.blitFrom(*frame);
|
||||
}
|
||||
}
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
surf->fill32(color, _xoff, _yoff, _currentFrame.w, _currentFrame.h);
|
||||
Common::Rect srcRect(_currentFrame.w, _currentFrame.h);
|
||||
surf->Blit(_currentFrame, srcRect, _xoff, _yoff);
|
||||
}
|
||||
|
||||
void AVIPlayer::run() {
|
||||
if (_decoder->endOfVideo()) {
|
||||
_playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
int AVIPlayer::getFrameNo() const {
|
||||
return _decoder->getCurFrame();
|
||||
}
|
||||
|
||||
void AVIPlayer::setOffset(int xoff, int yoff) {
|
||||
_xoff = xoff;
|
||||
_yoff = yoff;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
80
engines/ultima/ultima8/gfx/avi_player.h
Normal file
80
engines/ultima/ultima8/gfx/avi_player.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_AVIPLAYER_H
|
||||
#define ULTIMA8_GFX_AVIPLAYER_H
|
||||
|
||||
#include "ultima/ultima8/gfx/movie_player.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Video {
|
||||
class AVIDecoder;
|
||||
}
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class AVIPlayer : public MoviePlayer {
|
||||
public:
|
||||
//!
|
||||
//! Create a new player for the given stream at the given size. Playback is
|
||||
//! automatically scaled up using the line-skip style from Crusader, unless
|
||||
//! noScale flag is set.
|
||||
//! If overridePal is set, use that as the palette instead of the AVI's one.
|
||||
//!
|
||||
AVIPlayer(Common::SeekableReadStream *rs, int width, int height, const byte *overridePal, bool noScale);
|
||||
~AVIPlayer();
|
||||
|
||||
void run() override;
|
||||
void paint(RenderSurface *surf, int lerp) override;
|
||||
|
||||
void start() override;
|
||||
void stop() override;
|
||||
bool isPlaying() const override {
|
||||
return _playing;
|
||||
}
|
||||
|
||||
int getFrameNo() const;
|
||||
|
||||
// Adjust the offsets by the given values
|
||||
void setOffset(int xoff, int yoff) override;
|
||||
|
||||
private:
|
||||
|
||||
bool _playing;
|
||||
Video::AVIDecoder *_decoder;
|
||||
Graphics::ManagedSurface _currentFrame;
|
||||
// Width and height of the area we've been given to play back in
|
||||
uint32 _width;
|
||||
uint32 _height;
|
||||
// Xoff and Yoff into that playback area
|
||||
uint32 _xoff;
|
||||
uint32 _yoff;
|
||||
bool _doubleSize;
|
||||
const byte *_overridePal;
|
||||
bool _pausedMusic;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
144
engines/ultima/ultima8/gfx/cycle_process.cpp
Normal file
144
engines/ultima/ultima8/gfx/cycle_process.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/* 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 "ultima/ultima8/gfx/cycle_process.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
CycleProcess *CycleProcess::_instance = nullptr;
|
||||
|
||||
// Which color to cycle in each of the palette colors 8~14
|
||||
static const bool CYCLE_COL_FLAGS[7][3] = {
|
||||
{ 1, 0, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 1, 0, 0 },
|
||||
{ 0, 0, 1 },
|
||||
{ 1, 1, 0 },
|
||||
{ 1, 1, 1 },
|
||||
{ 0, 1, 0 }
|
||||
};
|
||||
|
||||
static const uint8 CYCLE_INIT_COLS[7][3] = {{ 0, 0, 0 }, { 0, 0, 0 }, { 124, 0, 0 }, { 0, 0, 124 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }};
|
||||
|
||||
static const bool CYCLE_RANDOMIZE[7] = {
|
||||
false, false, false, false, false, false, true
|
||||
};
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(CycleProcess)
|
||||
|
||||
static inline void copyColor(uint8 *dst, const uint8 *src) {
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
}
|
||||
|
||||
CycleProcess::CycleProcess() : Process(), _running(1) {
|
||||
_instance = this;
|
||||
_ticksPerRun = 2;
|
||||
_type = 1; // persistent
|
||||
for (int i = 0; i < 7; i++) {
|
||||
copyColor(_cycleColData[i], CYCLE_INIT_COLS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CycleProcess::~CycleProcess(void) {
|
||||
if (_instance == this)
|
||||
_instance = nullptr;
|
||||
}
|
||||
|
||||
CycleProcess *CycleProcess::get_instance() {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
static bool cycleColor(uint8 *col, const bool flags[3]) {
|
||||
bool wrapped = false;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (flags[i]) {
|
||||
col[i] += 8;
|
||||
}
|
||||
if (col[i] > 252) {
|
||||
col[i] = 0;
|
||||
wrapped = true;
|
||||
}
|
||||
}
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
void CycleProcess::run() {
|
||||
if (!_running)
|
||||
return;
|
||||
|
||||
PaletteManager *pm = PaletteManager::get_instance();
|
||||
Palette *pal = pm->getPalette(PaletteManager::Pal_Game);
|
||||
|
||||
// Step 1: Rotate 7 colors (1~7)
|
||||
byte r1, g1, b1;
|
||||
// tmp copy of color 1
|
||||
pal->get(1, r1, g1, b1);
|
||||
for (int i = 1; i < 7; i++) {
|
||||
byte r, g, b;
|
||||
pal->get(i + 1, r, g, b);
|
||||
pal->set(i, r, g, b);
|
||||
}
|
||||
// move color 1 -> color 7
|
||||
pal->set(7, r1, g1, b1);
|
||||
|
||||
Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
|
||||
|
||||
// Step 2: Cycle 7 other colors 8~14 by increasing their value
|
||||
// until they hit max, then reset.
|
||||
for (int i = 0; i < 7; i++) {
|
||||
bool wrapped = cycleColor(_cycleColData[i], CYCLE_COL_FLAGS[i]);
|
||||
if (CYCLE_RANDOMIZE[i] && wrapped) {
|
||||
_cycleColData[i][0] += rs.getRandomNumber(9);
|
||||
_cycleColData[i][1] += rs.getRandomNumber(9);
|
||||
_cycleColData[i][2] += rs.getRandomNumber(9);
|
||||
}
|
||||
pal->set(i + 8, _cycleColData[i][0], _cycleColData[i][1], _cycleColData[i][2]);
|
||||
}
|
||||
|
||||
// Update the cached palette.
|
||||
pm->updatedPalette(PaletteManager::Pal_Game, 16);
|
||||
}
|
||||
|
||||
void CycleProcess::saveData(Common::WriteStream *ws) {
|
||||
Process::saveData(ws);
|
||||
|
||||
ws->writeByte(_running);
|
||||
}
|
||||
|
||||
bool CycleProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
_running = rs->readByte();
|
||||
_instance = this; //static
|
||||
|
||||
_type = 1; // should be persistent but older savegames may not know that.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gfx/cycle_process.h
Normal file
63
engines/ultima/ultima8/gfx/cycle_process.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_CYCLEPROCESS_H
|
||||
#define ULTIMA8_GFX_CYCLEPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/** The process to cycle some palette colors in Crusader */
|
||||
class CycleProcess : public Process {
|
||||
uint8 _running;
|
||||
uint8 _cycleColData[7][3];
|
||||
public:
|
||||
static CycleProcess *_instance;
|
||||
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
CycleProcess();
|
||||
~CycleProcess() override;
|
||||
|
||||
void run() override;
|
||||
|
||||
static CycleProcess *get_instance();
|
||||
|
||||
void pauseCycle() {
|
||||
_running = 0;
|
||||
}
|
||||
|
||||
void resumeCycle() {
|
||||
_running = 1;
|
||||
}
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
98
engines/ultima/ultima8/gfx/fade_to_modal_process.cpp
Normal file
98
engines/ultima/ultima8/gfx/fade_to_modal_process.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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 "ultima/ultima8/gfx/palette_fader_process.h"
|
||||
#include "ultima/ultima8/gfx/fade_to_modal_process.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/gumps/gump_notify_process.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(FadeToModalProcess)
|
||||
|
||||
|
||||
FadeToModalProcess::FadeToModalProcess(ModalGump *modal)
|
||||
: _modal(modal), _nextState(FS_OpenFadeOut), _fader(nullptr)
|
||||
{
|
||||
setRunPaused();
|
||||
}
|
||||
|
||||
FadeToModalProcess::~FadeToModalProcess(void) {
|
||||
}
|
||||
|
||||
void FadeToModalProcess::onWakeUp() {
|
||||
if (_nextState == FS_CloseFadeIn) {
|
||||
// Jump in now and make sure the fade in is started (ie, we go to black)
|
||||
// before the modal is closed, otherwise a single frame of the thing
|
||||
// behind it will be shown first.
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0x00, 0x00, 0x00, 0x00), true, 0x7FFF, 30, false);
|
||||
_fader->run();
|
||||
}
|
||||
}
|
||||
|
||||
void FadeToModalProcess::run() {
|
||||
switch (_nextState) {
|
||||
case FS_OpenFadeOut:
|
||||
{
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0x00, 0x00, 0x00, 0x00), false, 0x7FFF, 30, true);
|
||||
Kernel::get_instance()->addProcess(_fader);
|
||||
_fader->setRunPaused();
|
||||
_nextState = FS_ShowGump;
|
||||
waitFor(_fader);
|
||||
break;
|
||||
}
|
||||
case FS_ShowGump:
|
||||
{
|
||||
// kernel will delete the fader object for us
|
||||
_fader = nullptr;
|
||||
_modal->InitGump(0);
|
||||
_modal->setRelativePosition(Gump::CENTER);
|
||||
_modal->CreateNotifier();
|
||||
// Reset the palette before showing the modal
|
||||
PaletteManager::get_instance()->untransformPalette(PaletteManager::Pal_Game);
|
||||
_nextState = FS_CloseFadeIn;
|
||||
waitFor(_modal->GetNotifyProcess());
|
||||
break;
|
||||
}
|
||||
case FS_CloseFadeIn:
|
||||
{
|
||||
// Already created a new fader in onWakeUp..
|
||||
Kernel::get_instance()->addProcess(_fader);
|
||||
_fader->setRunPaused();
|
||||
_nextState = FS_Finshed;
|
||||
waitFor(_fader);
|
||||
break;
|
||||
}
|
||||
case FS_Finshed:
|
||||
{
|
||||
// kernel will delete the fader object for us
|
||||
_fader = nullptr;
|
||||
terminate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
62
engines/ultima/ultima8/gfx/fade_to_modal_process.h
Normal file
62
engines/ultima/ultima8/gfx/fade_to_modal_process.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FADETOMODALPROCESS_H
|
||||
#define ULTIMA8_GFX_FADETOMODALPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/gumps/modal_gump.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class PaletteFaderProcess;
|
||||
|
||||
/** A process to fade out the screen and open a modal */
|
||||
class FadeToModalProcess : public Process {
|
||||
|
||||
enum FadeToModalState {
|
||||
FS_OpenFadeOut,
|
||||
FS_ShowGump,
|
||||
FS_CloseFadeIn,
|
||||
FS_Finshed
|
||||
} _nextState;
|
||||
|
||||
ModalGump * _modal;
|
||||
PaletteFaderProcess * _fader;
|
||||
|
||||
public:
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
FadeToModalProcess(ModalGump *modal);
|
||||
~FadeToModalProcess(void) override;
|
||||
|
||||
void onWakeUp() override;
|
||||
|
||||
void run() override;
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
383
engines/ultima/ultima8/gfx/fonts/font.cpp
Normal file
383
engines/ultima/ultima8/gfx/fonts/font.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
/* 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 "ultima/ultima.h"
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
Font::Font() : _highRes(false) {
|
||||
}
|
||||
|
||||
|
||||
Font::~Font() {
|
||||
}
|
||||
|
||||
|
||||
void Font::getTextSize(const Std::string &text,
|
||||
int32 &resultwidth, int32 &resultheight,
|
||||
unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align,
|
||||
bool u8specials, bool pagebreaks) {
|
||||
Std::list<PositionedText> tmp;
|
||||
tmp = typesetText<Traits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultwidth, resultheight);
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
bool Font::Traits::canBreakAfter(Std::string::const_iterator &i) {
|
||||
// It's not really relevant what we do here, because this probably will
|
||||
// not be used at normal font sizes.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//static
|
||||
bool Font::SJISTraits::canBreakAfter(Std::string::const_iterator &i) {
|
||||
Std::string::const_iterator j = i;
|
||||
uint32 u1 = unicode(j);
|
||||
|
||||
// See: https://wiki.wesnoth.org/index.php?title=JapaneseTranslation&oldid=23480#Word-Wrapping
|
||||
// and: https://ja.wikipedia.org/wiki/%E7%A6%81%E5%89%87
|
||||
|
||||
switch (u1) {
|
||||
case 0xff08:
|
||||
case 0x3014:
|
||||
case 0xff3b:
|
||||
case 0xff5b:
|
||||
case 0x3008:
|
||||
case 0x300a:
|
||||
case 0x300c:
|
||||
case 0x300e:
|
||||
case 0x3010:
|
||||
case 0x2018:
|
||||
case 0x201c:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint32 u2 = unicode(j);
|
||||
switch (u2) {
|
||||
case 0x3001:
|
||||
case 0x3002:
|
||||
case 0xff0c:
|
||||
case 0xff0e:
|
||||
case 0xff09:
|
||||
case 0x3015:
|
||||
case 0xff3d:
|
||||
case 0xff5d:
|
||||
case 0x3009:
|
||||
case 0x300b:
|
||||
case 0x300d:
|
||||
case 0x300f:
|
||||
case 0x3011:
|
||||
case 0x2019:
|
||||
case 0x201d:
|
||||
case 0x309d:
|
||||
case 0x309e:
|
||||
case 0x30fd:
|
||||
case 0x30fe:
|
||||
case 0x3005:
|
||||
case 0xff1f:
|
||||
case 0xff01:
|
||||
case 0xff1a:
|
||||
case 0xff1b:
|
||||
case 0x3041:
|
||||
case 0x3043:
|
||||
case 0x3045:
|
||||
case 0x3047:
|
||||
case 0x3049:
|
||||
case 0x3083:
|
||||
case 0x3085:
|
||||
case 0x3087:
|
||||
case 0x308e:
|
||||
case 0x30a1:
|
||||
case 0x30a3:
|
||||
case 0x30a5:
|
||||
case 0x30a7:
|
||||
case 0x30a9:
|
||||
case 0x30e3:
|
||||
case 0x30e5:
|
||||
case 0x30e7:
|
||||
case 0x30ee:
|
||||
case 0x3063:
|
||||
case 0x30f5:
|
||||
case 0x30c3:
|
||||
case 0x30f6:
|
||||
case 0x30fb:
|
||||
case 0x2026:
|
||||
case 0x30fc:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Also don't allow breaking between roman characters
|
||||
if (((u1 >= 'A' && u1 <= 'Z') || (u1 >= 'a' && u1 <= 'z')) &&
|
||||
((u2 >= 'A' && u2 <= 'Z') || (u2 >= 'a' && u2 <= 'z'))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void findWordEnd(const Std::string &text,
|
||||
Std::string::const_iterator &iter, bool u8specials) {
|
||||
while (iter != text.end()) {
|
||||
if (T::isSpace(iter, u8specials)) return;
|
||||
T::advance(iter);
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void passSpace(const Std::string &text,
|
||||
Std::string::const_iterator &iter, bool u8specials) {
|
||||
while (iter != text.end()) {
|
||||
if (!T::isSpace(iter, u8specials)) return;
|
||||
T::advance(iter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Special characters in U8:
|
||||
|
||||
@ = bullet for conversation options
|
||||
~ = line break
|
||||
% = tab
|
||||
* = line break on graves and plaques, possibly page break in books
|
||||
CHECKME: any others? (page breaks for books?)
|
||||
|
||||
*/
|
||||
|
||||
template<class T>
|
||||
Std::list<PositionedText> typesetText(Font *font,
|
||||
const Std::string &text, unsigned int &remaining, int32 width, int32 height,
|
||||
Font::TextAlign align, bool u8specials, bool pagebreaks, int32 &resultwidth,
|
||||
int32 &resultheight, Std::string::size_type cursor) {
|
||||
|
||||
debugC(kDebugGraphics, "typeset (%d, %d) %s", width, height, text.c_str());
|
||||
|
||||
// be optimistic and assume everything will fit
|
||||
remaining = text.size();
|
||||
|
||||
Std::string curline;
|
||||
|
||||
int totalwidth = 0;
|
||||
int totalheight = 0;
|
||||
|
||||
Std::list<PositionedText> lines;
|
||||
PositionedText line;
|
||||
|
||||
Std::string::const_iterator iter = text.begin();
|
||||
Std::string::const_iterator cursoriter = text.begin();
|
||||
if (cursor != Std::string::npos) cursoriter += cursor;
|
||||
Std::string::const_iterator curlinestart = text.begin();
|
||||
|
||||
bool breakhere = false;
|
||||
while (true) {
|
||||
if (iter == text.end() || breakhere || T::isBreak(iter, u8specials)) {
|
||||
// break here
|
||||
bool atpagebreak = pagebreaks && T::isPageBreak(iter, u8specials);
|
||||
int32 stringwidth = 0, stringheight = 0;
|
||||
font->getStringSize(curline, stringwidth, stringheight);
|
||||
line._dims.left = 0;
|
||||
line._dims.top = totalheight;
|
||||
line._dims.setWidth(stringwidth);
|
||||
line._dims.setHeight(stringheight);
|
||||
line._text = curline;
|
||||
line._cursor = Std::string::npos;
|
||||
if (cursor != Std::string::npos && cursoriter >= curlinestart &&
|
||||
(cursoriter < iter || (!breakhere && cursoriter == iter))) {
|
||||
line._cursor = cursoriter - curlinestart;
|
||||
if (line._dims.width() == 0) {
|
||||
stringwidth = 2;
|
||||
line._dims.setWidth(stringwidth);
|
||||
}
|
||||
}
|
||||
lines.push_back(line);
|
||||
|
||||
if (stringwidth > totalwidth) totalwidth = stringwidth;
|
||||
totalheight += font->getBaselineSkip();
|
||||
|
||||
curline = "";
|
||||
|
||||
if (iter == text.end())
|
||||
break; // done
|
||||
|
||||
if (breakhere) {
|
||||
breakhere = false;
|
||||
curlinestart = iter;
|
||||
} else {
|
||||
T::advance(iter);
|
||||
curlinestart = iter;
|
||||
}
|
||||
|
||||
if (atpagebreak || (height != 0 && totalheight + font->getHeight() > height)) {
|
||||
// next line won't fit
|
||||
remaining = curlinestart - text.begin();
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// see if next word still fits on the current line
|
||||
Std::string::const_iterator nextword = iter;
|
||||
passSpace<T>(text, nextword, u8specials);
|
||||
|
||||
// process spaces
|
||||
bool foundLF = false;
|
||||
Std::string spaces;
|
||||
for (; iter < nextword; T::advance(iter)) {
|
||||
if (T::isBreak(iter, u8specials)) {
|
||||
foundLF = true;
|
||||
break;
|
||||
} else if (T::isTab(iter, u8specials)) {
|
||||
// ignore tabs at beginning of line when centered
|
||||
if (!(curline.empty() && align == Font::TEXT_CENTER))
|
||||
spaces.append(" ");
|
||||
} else if (!curline.empty()) {
|
||||
spaces.append(" ");
|
||||
}
|
||||
}
|
||||
// no next word?
|
||||
if (foundLF || nextword == text.end()) continue;
|
||||
|
||||
// process word
|
||||
Std::string::const_iterator endofnextword = iter;
|
||||
findWordEnd<T>(text, endofnextword, u8specials);
|
||||
int32 stringwidth = 0, stringheight = 0;
|
||||
Std::string newline = curline + spaces +
|
||||
text.substr(nextword - text.begin(), endofnextword - nextword);
|
||||
font->getStringSize(newline, stringwidth, stringheight);
|
||||
|
||||
// if not, break line before this word
|
||||
if (width != 0 && stringwidth > width) {
|
||||
if (!curline.empty()) {
|
||||
iter = nextword;
|
||||
} else {
|
||||
// word is longer than the line; have to break in mid-word
|
||||
// FIXME: this is rather inefficient; binary search?
|
||||
// FIXME: clean up...
|
||||
iter = nextword;
|
||||
Std::string::const_iterator saveiter = nextword; // Dummy initialization
|
||||
Std::string::const_iterator saveiter_fail;
|
||||
Std::string curline_fail;
|
||||
newline = spaces;
|
||||
bool breakok = true;
|
||||
int breakcount = -1;
|
||||
do {
|
||||
if (breakok) {
|
||||
curline = newline;
|
||||
saveiter = iter;
|
||||
breakcount++;
|
||||
}
|
||||
curline_fail = newline;
|
||||
saveiter_fail = iter;
|
||||
|
||||
if (iter == text.end()) break;
|
||||
|
||||
breakok = T::canBreakAfter(iter);
|
||||
|
||||
// try next character
|
||||
T::advance(iter);
|
||||
newline = spaces + text.substr(nextword - text.begin(),
|
||||
iter - nextword);
|
||||
font->getStringSize(newline, stringwidth, stringheight);
|
||||
} while (stringwidth <= width);
|
||||
if (breakcount > 0) {
|
||||
iter = saveiter;
|
||||
} else {
|
||||
iter = saveiter_fail;
|
||||
curline = curline_fail;
|
||||
}
|
||||
}
|
||||
breakhere = true;
|
||||
continue;
|
||||
} else {
|
||||
// copy next word into curline
|
||||
curline = newline;
|
||||
iter = endofnextword;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lines.size() == 1 && align == Font::TEXT_LEFT) {
|
||||
// only one line, so use the actual text width
|
||||
width = totalwidth;
|
||||
}
|
||||
|
||||
if (width != 0) totalwidth = width;
|
||||
|
||||
// adjust total height
|
||||
totalheight -= font->getBaselineSkip();
|
||||
totalheight += font->getHeight();
|
||||
|
||||
// fixup x coordinates of lines
|
||||
for (auto &l : lines) {
|
||||
switch (align) {
|
||||
case Font::TEXT_LEFT:
|
||||
break;
|
||||
case Font::TEXT_RIGHT:
|
||||
l._dims.moveTo(totalwidth - l._dims.width(), l._dims.top);
|
||||
break;
|
||||
case Font::TEXT_CENTER:
|
||||
l._dims.moveTo((totalwidth - l._dims.width()) / 2, l._dims.top);
|
||||
break;
|
||||
}
|
||||
|
||||
debugC(kDebugGraphics, "%d, %d, %d, %d: %s", l._dims.left, l._dims.top,
|
||||
l._dims.width(), l._dims.height(), l._text.c_str());
|
||||
}
|
||||
|
||||
resultwidth = totalwidth;
|
||||
resultheight = totalheight;
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
// explicit instantiations
|
||||
template
|
||||
Std::list<PositionedText> typesetText<Font::Traits>
|
||||
(Font *font, const Std::string &text,
|
||||
unsigned int &remaining, int32 width, int32 height,
|
||||
Font::TextAlign align, bool u8specials, bool pagebreaks,
|
||||
int32 &resultwidth, int32 &resultheight, Std::string::size_type cursor);
|
||||
|
||||
template
|
||||
Std::list<PositionedText> typesetText<Font::SJISTraits>
|
||||
(Font *font, const Std::string &text,
|
||||
unsigned int &remaining, int32 width, int32 height,
|
||||
Font::TextAlign align, bool u8specials, bool pagebreaks,
|
||||
int32 &resultwidth, int32 &resultheight, Std::string::size_type cursor);
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
180
engines/ultima/ultima8/gfx/fonts/font.h
Normal file
180
engines/ultima/ultima8/gfx/fonts/font.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_FONT_H
|
||||
#define ULTIMA8_GFX_FONTS_FONT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "ultima/ultima8/misc/encoding.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderedText;
|
||||
|
||||
struct PositionedText {
|
||||
Std::string _text;
|
||||
Common::Rect32 _dims;
|
||||
Std::string::size_type _cursor;
|
||||
};
|
||||
|
||||
class Font {
|
||||
public:
|
||||
Font();
|
||||
virtual ~Font();
|
||||
|
||||
enum TextAlign {
|
||||
TEXT_LEFT,
|
||||
TEXT_CENTER,
|
||||
TEXT_RIGHT
|
||||
};
|
||||
|
||||
//! get the height of the font
|
||||
virtual int getHeight() = 0;
|
||||
|
||||
//! get the baseline of the font (relative from the top)
|
||||
virtual int getBaseline() = 0;
|
||||
|
||||
//! get the baselineskip of the font (distance between two baselines)
|
||||
virtual int getBaselineSkip() = 0;
|
||||
|
||||
//! get the dimensions of a string (not containing any newlines)
|
||||
//! \param text The string
|
||||
//! \param width Returns the width
|
||||
//! \param height Returns the height
|
||||
virtual void getStringSize(const Std::string &text,
|
||||
int32 &width, int32 &height) = 0;
|
||||
|
||||
//! render a string
|
||||
//! \param text The text
|
||||
//! \param remaining Returns index of the first character not printed
|
||||
//! \param width The width of the target rectangle, or 0 for unlimited
|
||||
//! \param height The height of the target rectangle, or 0 for unlimited
|
||||
//! \param align Alignment of the text (left, right, center)
|
||||
//! \param u8specials If true, interpret the special characters U8 uses
|
||||
//! \param pagebreaks If true (and u8specials too), stop at U8 pagebreaks
|
||||
//! \return the rendered text in a RenderedText object
|
||||
virtual RenderedText *renderText(const Std::string &text,
|
||||
unsigned int &remaining, int32 width = 0, int32 height = 0,
|
||||
TextAlign align = TEXT_LEFT, bool u8specials = false,
|
||||
bool pagebreaks = false,
|
||||
Std::string::size_type cursor = Std::string::npos) = 0;
|
||||
|
||||
//! get the dimensions of a rendered string
|
||||
//! \param text The text
|
||||
//! \param resultwidth Returns the resulting width
|
||||
//! \param resultheight Returns the resulting height
|
||||
//! \param remaining Returns index of the first character not printed
|
||||
//! \param width The width of the target rectangle, or 0 for unlimited
|
||||
//! \param height The height of the target rectangle, or 0 for unlimited
|
||||
//! \param align Alignment of the text (left, right, center)
|
||||
//! \param u8specials If true, interpret the special characters U8 uses
|
||||
//! \param pagebreaks If true (and u8specials too), stop at U8 pagebreaks
|
||||
virtual void getTextSize(const Std::string &text,
|
||||
int32 &resultwidth, int32 &resultheight, unsigned int &remaining,
|
||||
int32 width = 0, int32 height = 0, TextAlign align = TEXT_LEFT,
|
||||
bool u8specials = false, bool pagebreaks = false);
|
||||
|
||||
void setHighRes(bool hr) {
|
||||
_highRes = hr;
|
||||
}
|
||||
bool isHighRes() const {
|
||||
return _highRes;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool _highRes;
|
||||
|
||||
struct Traits {
|
||||
static bool isSpace(Std::string::const_iterator &i, bool u8specials) {
|
||||
char c = *i;
|
||||
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' ||
|
||||
(u8specials && (c == '%' || c == '~' || c == '*' || c == '^')));
|
||||
}
|
||||
static bool isTab(Std::string::const_iterator &i, bool u8specials) {
|
||||
char c = *i;
|
||||
return (c == '\t' ||
|
||||
(u8specials && (c == '\t' || c == '%')));
|
||||
}
|
||||
static bool isBreak(Std::string::const_iterator &i, bool u8specials) {
|
||||
char c = *i;
|
||||
return (c == '\n' ||
|
||||
(u8specials && (c == '\n' || c == '~' || c == '*')));
|
||||
}
|
||||
static bool isPageBreak(Std::string::const_iterator &i, bool u8specials) {
|
||||
char c = *i;
|
||||
return (u8specials && c == '*');
|
||||
}
|
||||
static bool canBreakAfter(Std::string::const_iterator &i);
|
||||
static void advance(Std::string::const_iterator &i) {
|
||||
++i;
|
||||
}
|
||||
static Std::string::size_type length(const Std::string &t) {
|
||||
return t.size();
|
||||
}
|
||||
static uint32 unicode(Std::string::const_iterator &i) {
|
||||
return encoding[static_cast<uint8>(*i++)];
|
||||
}
|
||||
};
|
||||
struct SJISTraits : public Traits {
|
||||
static bool canBreakAfter(Std::string::const_iterator &i);
|
||||
static void advance(Std::string::const_iterator &i) {
|
||||
// FIXME: this can advance past the end of a malformed string
|
||||
uint8 c = *i;
|
||||
i++;
|
||||
if (c >= 0x80) i++;
|
||||
}
|
||||
static Std::string::size_type length(const Std::string &t) {
|
||||
Std::string::size_type l = 0;
|
||||
Std::string::const_iterator iter = t.begin();
|
||||
while (iter != t.end()) {
|
||||
advance(iter);
|
||||
l++;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
static uint32 unicode(Std::string::const_iterator &i) {
|
||||
uint16 s = static_cast<uint8>(*i);
|
||||
i++;
|
||||
if (s >= 0x80) {
|
||||
uint16 t = static_cast<uint8>(*i++);
|
||||
s |= (t << 8);
|
||||
}
|
||||
return shiftjis_to_unicode(s);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
Std::list<PositionedText> typesetText(Font *font,
|
||||
const Std::string &text, unsigned int &remaining,
|
||||
int32 width, int32 height, Font::TextAlign align,
|
||||
bool u8specials, bool pagebreaks,
|
||||
int32 &resultwidth, int32 &resultheight,
|
||||
Std::string::size_type cursor = Std::string::npos);
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
212
engines/ultima/ultima8/gfx/fonts/font_manager.cpp
Normal file
212
engines/ultima/ultima8/gfx/fonts/font_manager.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/* 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/file.h"
|
||||
|
||||
#include "ultima/ultima.h"
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/fonts/tt_font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/jp_font.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
|
||||
#include "graphics/fonts/ttf.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
FontManager *FontManager::_fontManager = nullptr;
|
||||
|
||||
FontManager::FontManager() {
|
||||
debug(1, "Creating Font Manager...");
|
||||
|
||||
_fontManager = this;
|
||||
|
||||
ConfMan.registerDefault("font_highres", true);
|
||||
}
|
||||
|
||||
FontManager::~FontManager() {
|
||||
debug(1, "Destroying Font Manager...");
|
||||
|
||||
resetGameFonts();
|
||||
|
||||
assert(_fontManager == this);
|
||||
_fontManager = nullptr;
|
||||
}
|
||||
|
||||
// Reset the font manager
|
||||
void FontManager::resetGameFonts() {
|
||||
for (unsigned int i = 0; i < _overrides.size(); ++i)
|
||||
delete _overrides[i];
|
||||
_overrides.clear();
|
||||
|
||||
for (unsigned int i = 0; i < _ttFonts.size(); ++i)
|
||||
delete _ttFonts[i];
|
||||
_ttFonts.clear();
|
||||
|
||||
for (auto &i : _ttfFonts)
|
||||
delete i._value;
|
||||
_ttfFonts.clear();}
|
||||
|
||||
Font *FontManager::getGameFont(unsigned int fontnum,
|
||||
bool allowOverride) {
|
||||
if (allowOverride && fontnum < _overrides.size() && _overrides[fontnum])
|
||||
return _overrides[fontnum];
|
||||
|
||||
return GameData::get_instance()->getFonts()->getFont(fontnum);
|
||||
}
|
||||
|
||||
Font *FontManager::getTTFont(unsigned int fontnum) {
|
||||
if (fontnum >= _ttFonts.size())
|
||||
return nullptr;
|
||||
return _ttFonts[fontnum];
|
||||
}
|
||||
|
||||
|
||||
Graphics::Font *FontManager::getTTF_Font(const Common::Path &filename, int pointsize, bool antialiasing) {
|
||||
#ifdef USE_FREETYPE2
|
||||
TTFId id;
|
||||
id._filename = filename;
|
||||
id._pointSize = pointsize;
|
||||
|
||||
TTFFonts::iterator iter;
|
||||
iter = _ttfFonts.find(id);
|
||||
|
||||
if (iter != _ttfFonts.end())
|
||||
return iter->_value;
|
||||
|
||||
Common::File* fontids = new Common::File();
|
||||
if (!fontids->open(filename)) {
|
||||
warning("Failed to open TTF: %s", filename.toString().c_str());
|
||||
delete fontids;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// open font using ScummVM TTF API
|
||||
// Note: The RWops and ReadStream will be deleted by the TTF_Font
|
||||
Graphics::TTFRenderMode mode = antialiasing ? Graphics::kTTFRenderModeNormal : Graphics::kTTFRenderModeMonochrome;
|
||||
Graphics::Font *font = Graphics::loadTTFFont(fontids, DisposeAfterUse::YES, pointsize, Graphics::kTTFSizeModeCharacter, 0, 0, mode, 0, false);
|
||||
|
||||
if (!font) {
|
||||
warning("Failed to open TTF: %s", filename.toString().c_str());
|
||||
delete fontids;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_ttfFonts[id] = font;
|
||||
|
||||
debugC(kDebugGraphics, "Opened TTF: %s.", filename.toString().c_str());
|
||||
return font;
|
||||
#else // !USE_FREETYPE2
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FontManager::setOverride(unsigned int fontnum, Font *newFont) {
|
||||
if (fontnum >= _overrides.size())
|
||||
_overrides.resize(fontnum + 1);
|
||||
|
||||
if (_overrides[fontnum])
|
||||
delete _overrides[fontnum];
|
||||
|
||||
_overrides[fontnum] = newFont;
|
||||
}
|
||||
|
||||
|
||||
bool FontManager::addTTFOverride(unsigned int fontnum, const Common::Path &filename,
|
||||
int pointsize, uint32 rgb, int bordersize,
|
||||
bool SJIS) {
|
||||
bool antialiasing = ConfMan.getBool("font_antialiasing");
|
||||
Graphics::Font *f = getTTF_Font(filename, pointsize, antialiasing);
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
TTFont *font = new TTFont(f, rgb, bordersize, antialiasing, SJIS);
|
||||
bool highres = ConfMan.getBool("font_highres");
|
||||
font->setHighRes(highres);
|
||||
|
||||
setOverride(fontnum, font);
|
||||
|
||||
debugC(kDebugGraphics, "Added TTF override for font %u", fontnum);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FontManager::addJPOverride(unsigned int fontnum,
|
||||
unsigned int jpfont, uint32 rgb) {
|
||||
ShapeFont *jf = dynamic_cast<ShapeFont *>(GameData::get_instance()->getFonts()->getFont(jpfont));
|
||||
if (!jf)
|
||||
return false;
|
||||
|
||||
JPFont *font = new JPFont(jf, fontnum);
|
||||
|
||||
setOverride(fontnum, font);
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
PaletteManager::PalIndex fontpal = static_cast<PaletteManager::PalIndex>
|
||||
(PaletteManager::Pal_JPFontStart + fontnum);
|
||||
palman->duplicate(PaletteManager::Pal_Game, fontpal);
|
||||
Palette *pal = palman->getPalette(fontpal);
|
||||
// TODO: maybe a small gradient
|
||||
// the main text uses index 3
|
||||
// indices 1,2 and 3 are in use for the bullets for conversation options
|
||||
for (int i = 1; i < 4; ++i) {
|
||||
pal->set(i, (rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, (rgb) & 0xFF);
|
||||
}
|
||||
palman->updatedPalette(fontpal);
|
||||
|
||||
debugC(kDebugGraphics, "Added JP override for font %u", fontnum);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool FontManager::loadTTFont(unsigned int fontnum, const Common::Path &filename,
|
||||
int pointsize, uint32 rgb, int bordersize) {
|
||||
bool antialiasing = ConfMan.getBool("font_antialiasing");
|
||||
Graphics::Font *f = getTTF_Font(filename, pointsize, antialiasing);
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
TTFont *font = new TTFont(f, rgb, bordersize, antialiasing, false);
|
||||
|
||||
// TODO: check if this is indeed what we want for non-gamefonts
|
||||
bool highres = ConfMan.getBool("font_highres");
|
||||
font->setHighRes(highres);
|
||||
|
||||
if (fontnum >= _ttFonts.size())
|
||||
_ttFonts.resize(fontnum + 1);
|
||||
|
||||
if (_ttFonts[fontnum])
|
||||
delete _ttFonts[fontnum];
|
||||
|
||||
_ttFonts[fontnum] = font;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
126
engines/ultima/ultima8/gfx/fonts/font_manager.h
Normal file
126
engines/ultima/ultima8/gfx/fonts/font_manager.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_FONTMANAGER_H
|
||||
#define ULTIMA8_GFX_FONTS_FONTMANAGER_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/shared/std/string.h"
|
||||
#include "common/path.h"
|
||||
#include "graphics/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Font;
|
||||
|
||||
// This is TTF_Font struct
|
||||
typedef struct _TTF_Font TTF_Font;
|
||||
|
||||
class TTFont;
|
||||
|
||||
|
||||
class FontManager {
|
||||
private:
|
||||
struct TTFId {
|
||||
Common::Path _filename;
|
||||
int _pointSize;
|
||||
bool operator<(const TTFId &other) const {
|
||||
return (_pointSize < other._pointSize ||
|
||||
(_pointSize == other._pointSize &&
|
||||
_filename < other._filename));
|
||||
}
|
||||
};
|
||||
|
||||
struct TTFHash {
|
||||
uint operator()(const TTFId &x) const {
|
||||
// TODO: See if something better can be used as a hash key
|
||||
int64 val = (int64)&x;
|
||||
return (uint)val;
|
||||
}
|
||||
};
|
||||
struct TTFEqual {
|
||||
bool operator()(const TTFId &x, const TTFId &y) const {
|
||||
return x._filename == y._filename && x._pointSize == y._pointSize;
|
||||
}
|
||||
};
|
||||
|
||||
typedef Common::HashMap<TTFId, Graphics::Font *, TTFHash, TTFEqual> TTFFonts;
|
||||
TTFFonts _ttfFonts;
|
||||
|
||||
//! Get a (possibly cached) TTF_Font structure for filename/pointsize,
|
||||
//! loading it if necessary.
|
||||
Graphics::Font *getTTF_Font(const Common::Path &filename, int pointsize, bool antialiasing);
|
||||
|
||||
//! Override fontnum with specified font
|
||||
void setOverride(unsigned int fontnum, Font *newFont);
|
||||
|
||||
Std::vector<Font *> _overrides;
|
||||
|
||||
Std::vector<Font *> _ttFonts;
|
||||
|
||||
static FontManager *_fontManager;
|
||||
public:
|
||||
FontManager();
|
||||
~FontManager();
|
||||
|
||||
static FontManager *get_instance() {
|
||||
return _fontManager;
|
||||
}
|
||||
|
||||
//! get a Font by fontnum (for game fonts)
|
||||
//! \param fontnum the number of the font
|
||||
//! \param allowOverride if true, allow an override font to be used
|
||||
Font *getGameFont(unsigned int fontnum,
|
||||
bool allowOverride = false);
|
||||
|
||||
//! get a TTF font (for non-game fonts)
|
||||
Font *getTTFont(unsigned int ttfnum);
|
||||
|
||||
//! override a game font with a TTF.
|
||||
//! \param fontnum the font to override
|
||||
//! \param filename the filename of the TTF
|
||||
//! \param pointsize the pointsize to use
|
||||
//! \param rgb the color to use for the font
|
||||
//! \param bordersize the size of the black border to add
|
||||
//! \param SJIS true for a Japanese game font
|
||||
bool addTTFOverride(unsigned int fontnum, const Common::Path &filename,
|
||||
int pointsize, uint32 rgb, int bordersize,
|
||||
bool SJIS = false);
|
||||
|
||||
//! override a game font with a Japanese font.
|
||||
//! \param fontnum the font to override
|
||||
//! \param jpfont the fontnum of the Japanese font to use
|
||||
//! \param rgb the color to use
|
||||
bool addJPOverride(unsigned int fontnum, unsigned int jpfont, uint32 rgb);
|
||||
|
||||
//! load a TTF (for non-game fonts)
|
||||
bool loadTTFont(unsigned int ttfnum, const Common::Path &filename,
|
||||
int pointsize, uint32 rgb, int bordersize);
|
||||
|
||||
// Reset the game fonts
|
||||
void resetGameFonts();
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima // End of namespace Ultima8
|
||||
|
||||
#endif
|
||||
90
engines/ultima/ultima8/gfx/fonts/font_shape_archive.cpp
Normal file
90
engines/ultima/ultima8/gfx/fonts/font_shape_archive.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font_shape_archive.h"
|
||||
#include "ultima/ultima8/misc/util.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/conf/config_file_manager.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ShapeFont *FontShapeArchive::getFont(uint32 fontnum) {
|
||||
return dynamic_cast<ShapeFont *>(getShape(fontnum));
|
||||
}
|
||||
|
||||
void FontShapeArchive::cache(uint32 shapenum) {
|
||||
if (shapenum >= _count) return;
|
||||
if (_shapes.empty()) _shapes.resize(_count);
|
||||
|
||||
if (_shapes[shapenum]) return;
|
||||
|
||||
uint32 shpsize;
|
||||
uint8 *data = getRawObject(shapenum, &shpsize);
|
||||
|
||||
if (!data || shpsize == 0) return;
|
||||
|
||||
// Auto detect format
|
||||
if (!_format)
|
||||
_format = Shape::DetectShapeFormat(data, shpsize);
|
||||
|
||||
if (!_format) {
|
||||
delete [] data;
|
||||
warning("Unable to detect shape format for flex.");
|
||||
return;
|
||||
}
|
||||
|
||||
Shape *shape = new ShapeFont(data, shpsize, _format, _id, shapenum);
|
||||
if (_palette) shape->setPalette(_palette);
|
||||
|
||||
_shapes[shapenum] = shape;
|
||||
}
|
||||
|
||||
void FontShapeArchive::setHVLeads() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
|
||||
KeyMap leadkeyvals = config->listKeyValues("game", "fontleads");
|
||||
for (const auto &i : leadkeyvals) {
|
||||
int fontnum = atoi(i._key.c_str());
|
||||
Std::string leaddesc = i._value;
|
||||
|
||||
Std::vector<Std::string> vals;
|
||||
SplitString(leaddesc, ',', vals);
|
||||
if (vals.size() != 2) {
|
||||
warning("Invalid hlead/vlead description: %s", leaddesc.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
int hlead = atoi(vals[0].c_str());
|
||||
int vlead = atoi(vals[1].c_str());
|
||||
|
||||
ShapeFont *font = getFont(fontnum);
|
||||
if (font) {
|
||||
font->setHLead(hlead);
|
||||
font->setVLead(vlead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
54
engines/ultima/ultima8/gfx/fonts/font_shape_archive.h
Normal file
54
engines/ultima/ultima8/gfx/fonts/font_shape_archive.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_FONTSHAPEARCHIVE_H
|
||||
#define ULTIMA8_GFX_FONTS_FONTSHAPEARCHIVE_H
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFont;
|
||||
|
||||
class FontShapeArchive : public ShapeArchive {
|
||||
public:
|
||||
FontShapeArchive(uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(id, pal, format) { }
|
||||
FontShapeArchive(Common::SeekableReadStream *rs, uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(rs, id, pal, format) { }
|
||||
|
||||
~FontShapeArchive() override { }
|
||||
|
||||
//! load HVLeads from u8.ini
|
||||
void setHVLeads();
|
||||
|
||||
ShapeFont *getFont(uint32 fontnum);
|
||||
|
||||
void cache(uint32 fontnum) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
105
engines/ultima/ultima8/gfx/fonts/jp_font.cpp
Normal file
105
engines/ultima/ultima8/gfx/fonts/jp_font.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/jp_font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/fonts/jp_rendered_text.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
JPFont::JPFont(ShapeFont *jpfont, unsigned int fontnum)
|
||||
: _fontNum(fontnum), _shapeFont(jpfont) {
|
||||
assert(_shapeFont->frameCount() > 256);
|
||||
}
|
||||
|
||||
|
||||
JPFont::~JPFont() {
|
||||
}
|
||||
|
||||
int JPFont::getWidth(int c) {
|
||||
return _shapeFont->getFrame(c)->_width;
|
||||
}
|
||||
|
||||
int JPFont::getHeight() {
|
||||
return _shapeFont->getHeight();
|
||||
}
|
||||
|
||||
int JPFont::getBaseline() {
|
||||
return _shapeFont->getBaseline();
|
||||
}
|
||||
|
||||
int JPFont::getBaselineSkip() {
|
||||
return _shapeFont->getBaselineSkip();
|
||||
}
|
||||
|
||||
|
||||
void JPFont::getStringSize(const Std::string &text, int32 &width, int32 &height) {
|
||||
int hlead = _shapeFont->getHlead();
|
||||
width = hlead;
|
||||
height = getHeight();
|
||||
|
||||
for (unsigned int i = 0; i < text.size(); ++i) {
|
||||
if (text[i] == '\n' || text[i] == '\r') {
|
||||
// ignore
|
||||
} else {
|
||||
uint16 sjis = text[i] & 0xFF;
|
||||
if (sjis >= 0x80) {
|
||||
uint16 t = text[++i] & 0xFF;
|
||||
sjis += (t << 8);
|
||||
}
|
||||
width += getWidth(shiftjis_to_ultima8(sjis)) - hlead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JPFont::getTextSize(const Std::string &text,
|
||||
int32 &resultwidth, int32 &resultheight,
|
||||
unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align,
|
||||
bool u8specials, bool pagebreaks) {
|
||||
Std::list<PositionedText> tmp;
|
||||
tmp = typesetText<SJISTraits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultwidth, resultheight);
|
||||
}
|
||||
|
||||
RenderedText *JPFont::renderText(const Std::string &text,
|
||||
unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align,
|
||||
bool u8specials, bool pagebreaks,
|
||||
Std::string::size_type cursor) {
|
||||
int32 resultwidth, resultheight;
|
||||
Std::list<PositionedText> lines;
|
||||
lines = typesetText<SJISTraits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultwidth, resultheight,
|
||||
cursor);
|
||||
|
||||
return new JPRenderedText(lines, resultwidth, resultheight,
|
||||
_shapeFont->getVlead(), _shapeFont, _fontNum);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
65
engines/ultima/ultima8/gfx/fonts/jp_font.h
Normal file
65
engines/ultima/ultima8/gfx/fonts/jp_font.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_JPFONT_H
|
||||
#define ULTIMA8_GFX_FONTS_JPFONT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFont;
|
||||
|
||||
class JPFont : public Font {
|
||||
public:
|
||||
JPFont(ShapeFont *jpfont, unsigned int fontnum);
|
||||
~JPFont() override;
|
||||
|
||||
int getWidth(int c);
|
||||
|
||||
int getHeight() override;
|
||||
int getBaseline() override;
|
||||
int getBaselineSkip() override;
|
||||
|
||||
void getStringSize(const Std::string &text,
|
||||
int32 &width, int32 &height) override;
|
||||
void getTextSize(const Std::string &text, int32 &resultwidth,
|
||||
int32 &resultheight, unsigned int &remaining, int32 width = 0,
|
||||
int32 height = 0, TextAlign align = TEXT_LEFT,
|
||||
bool u8specials = false, bool pagebreaks = false) override;
|
||||
|
||||
RenderedText *renderText(const Std::string &text,
|
||||
unsigned int &remaining, int32 width = 0, int32 height = 0,
|
||||
TextAlign align = TEXT_LEFT, bool u8specials = false,
|
||||
bool pagebreaks = false,
|
||||
Std::string::size_type cursor = Std::string::npos) override;
|
||||
|
||||
protected:
|
||||
|
||||
unsigned int _fontNum;
|
||||
ShapeFont *_shapeFont;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
127
engines/ultima/ultima8/gfx/fonts/jp_rendered_text.cpp
Normal file
127
engines/ultima/ultima8/gfx/fonts/jp_rendered_text.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/jp_rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
JPRenderedText::JPRenderedText(Std::list<PositionedText> &lines, int width, int height,
|
||||
int vLead, ShapeFont *font, unsigned int fontNum)
|
||||
: _lines(lines), _font(font), _fontNum(fontNum) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_vLead = vLead;
|
||||
}
|
||||
|
||||
JPRenderedText::~JPRenderedText() {
|
||||
}
|
||||
|
||||
void JPRenderedText::draw(RenderSurface *surface, int x, int y, bool /*destmasked*/) {
|
||||
// TODO support masking here??
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
PaletteManager::PalIndex fontpal = static_cast<PaletteManager::PalIndex>
|
||||
(PaletteManager::Pal_JPFontStart + _fontNum);
|
||||
Palette *pal = palman->getPalette(fontpal);
|
||||
const Palette *savepal = _font->getPalette();
|
||||
_font->setPalette(pal);
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
|
||||
for (const auto &line : _lines) {
|
||||
int line_x = x + line._dims.left;
|
||||
int line_y = y + line._dims.top;
|
||||
|
||||
size_t textsize = line._text.size();
|
||||
|
||||
for (size_t i = 0; i < textsize; ++i) {
|
||||
uint16 sjis = line._text[i] & 0xFF;
|
||||
if (sjis >= 0x80) {
|
||||
uint16 t = line._text[++i] & 0xFF;
|
||||
sjis += (t << 8);
|
||||
}
|
||||
uint16 u8char = shiftjis_to_ultima8(sjis);
|
||||
surface->Paint(_font, u8char, line_x, line_y);
|
||||
|
||||
if (i == line._cursor) {
|
||||
surface->fill32(color, line_x, line_y - _font->getBaseline(),
|
||||
1, line._dims.height());
|
||||
}
|
||||
|
||||
line_x += (_font->getFrame(u8char))->_width - _font->getHlead();
|
||||
}
|
||||
|
||||
if (line._cursor == textsize) {
|
||||
surface->fill32(color, line_x, line_y - _font->getBaseline(),
|
||||
1, line._dims.height());
|
||||
}
|
||||
}
|
||||
|
||||
_font->setPalette(savepal);
|
||||
}
|
||||
|
||||
void JPRenderedText::drawBlended(RenderSurface *surface, int x, int y,
|
||||
uint32 col, bool /*destmasked*/) {
|
||||
// TODO Support masking here??
|
||||
|
||||
PaletteManager *palman = PaletteManager::get_instance();
|
||||
PaletteManager::PalIndex fontpal = static_cast<PaletteManager::PalIndex>
|
||||
(PaletteManager::Pal_JPFontStart + _fontNum);
|
||||
Palette *pal = palman->getPalette(fontpal);
|
||||
const Palette *savepal = _font->getPalette();
|
||||
_font->setPalette(pal);
|
||||
|
||||
Std::list<PositionedText>::const_iterator iter;
|
||||
|
||||
for (const auto &line : _lines) {
|
||||
int line_x = x + line._dims.left;
|
||||
int line_y = y + line._dims.top;
|
||||
|
||||
size_t textsize = line._text.size();
|
||||
|
||||
for (size_t i = 0; i < textsize; ++i) {
|
||||
uint16 sjis = line._text[i] & 0xFF;
|
||||
if (sjis >= 0x80) {
|
||||
uint16 t = line._text[++i] & 0xFF;
|
||||
sjis += (t << 8);
|
||||
}
|
||||
uint16 u8char = shiftjis_to_ultima8(sjis);
|
||||
|
||||
surface->PaintHighlight(_font, u8char, line_x, line_y,
|
||||
false, false, col);
|
||||
line_x += (_font->getFrame(u8char))->_width - _font->getHlead();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_font->setPalette(savepal);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
52
engines/ultima/ultima8/gfx/fonts/jp_rendered_text.h
Normal file
52
engines/ultima/ultima8/gfx/fonts/jp_rendered_text.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_JPRENDEREDTEXT_H
|
||||
#define ULTIMA8_GFX_FONTS_JPRENDEREDTEXT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFont;
|
||||
|
||||
class JPRenderedText : public RenderedText {
|
||||
public:
|
||||
JPRenderedText(Std::list<PositionedText> &lines,
|
||||
int width, int height, int vlead, ShapeFont *font,
|
||||
unsigned int fontnum);
|
||||
~JPRenderedText() override;
|
||||
|
||||
void draw(RenderSurface *surface, int x, int y, bool destmasked = false) override;
|
||||
void drawBlended(RenderSurface *surface, int x, int y, uint32 col, bool destmasked = false) override;
|
||||
|
||||
protected:
|
||||
Std::list<PositionedText> _lines;
|
||||
ShapeFont *_font;
|
||||
unsigned int _fontNum;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
37
engines/ultima/ultima8/gfx/fonts/rendered_text.cpp
Normal file
37
engines/ultima/ultima8/gfx/fonts/rendered_text.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
RenderedText::RenderedText()
|
||||
: _width(-1), _height(-1), _vLead(0) {
|
||||
}
|
||||
|
||||
|
||||
RenderedText::~RenderedText() {
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
65
engines/ultima/ultima8/gfx/fonts/rendered_text.h
Normal file
65
engines/ultima/ultima8/gfx/fonts/rendered_text.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_RENDEREDTEXT_H
|
||||
#define ULTIMA8_GFX_FONTS_RENDEREDTEXT_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderSurface;
|
||||
|
||||
class RenderedText {
|
||||
public:
|
||||
RenderedText();
|
||||
virtual ~RenderedText();
|
||||
|
||||
//! Draw self to a rendersurface.
|
||||
//! \param surface The surface to draw to
|
||||
//! \param x X coordinate of target
|
||||
//! \param y Y coordinate of target. This will be the top baseline.
|
||||
virtual void draw(RenderSurface *surface, int x, int y, bool destmasked = false) = 0;
|
||||
|
||||
//! Draw self to a rendersurface blended (0xAABBGGRR, alpha is blend level)
|
||||
virtual void drawBlended(RenderSurface *surface, int x, int y, uint32 col, bool destmasked = false) = 0;
|
||||
|
||||
//! Get dimensions.
|
||||
//! \param x Returns the width
|
||||
//! \param y Returns the height
|
||||
virtual void getSize(int &x, int &y) const {
|
||||
x = _width;
|
||||
y = _height;
|
||||
}
|
||||
|
||||
//! Get vlead
|
||||
virtual int getVlead() {
|
||||
return _vLead;
|
||||
}
|
||||
|
||||
protected:
|
||||
int _width, _height;
|
||||
int _vLead;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
137
engines/ultima/ultima8/gfx/fonts/shape_font.cpp
Normal file
137
engines/ultima/ultima8/gfx/fonts/shape_font.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_rendered_text.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ShapeFont::ShapeFont(const uint8 *data, uint32 size,
|
||||
const ConvertShapeFormat *format,
|
||||
const uint16 flexId, const uint32 shapeNum)
|
||||
: Font(), Shape(data, size, format, flexId, shapeNum),
|
||||
_height(0), _baseLine(0), _vLead(-1), _hLead(0) {
|
||||
_crusaderCharMap = GAME_IS_CRUSADER && shapeNum == 1;
|
||||
}
|
||||
|
||||
ShapeFont::~ShapeFont() {
|
||||
}
|
||||
|
||||
|
||||
int ShapeFont::getWidth(char c) {
|
||||
const ShapeFrame *frame = getFrame(charToFrameNum(c));
|
||||
if (frame)
|
||||
return frame->_width;
|
||||
else
|
||||
return 7; // small space..
|
||||
}
|
||||
|
||||
int ShapeFont::getHeight() {
|
||||
if (_height == 0) {
|
||||
for (uint32 i = 0; i < frameCount(); i++) {
|
||||
const ShapeFrame *frame = getFrame(i);
|
||||
if (!frame)
|
||||
continue;
|
||||
int h = frame->_height;
|
||||
|
||||
if (h > _height) _height = h;
|
||||
}
|
||||
}
|
||||
|
||||
return _height;
|
||||
}
|
||||
|
||||
int ShapeFont::getBaseline() {
|
||||
if (_baseLine == 0) {
|
||||
for (uint32 i = 0; i < frameCount(); i++) {
|
||||
int b = getFrame(i)->_yoff;
|
||||
|
||||
if (b > _baseLine) _baseLine = b;
|
||||
}
|
||||
}
|
||||
|
||||
return _baseLine;
|
||||
}
|
||||
|
||||
int ShapeFont::getBaselineSkip() {
|
||||
return getHeight() + getVlead();
|
||||
}
|
||||
|
||||
void ShapeFont::getStringSize(const Std::string &text, int32 &width, int32 &height) {
|
||||
width = _hLead;
|
||||
height = getHeight();
|
||||
|
||||
for (unsigned int i = 0; i < text.size(); ++i) {
|
||||
if (text[i] == '\n' || text[i] == '\r') {
|
||||
// ignore
|
||||
} else {
|
||||
width += getWidth(text[i]) - _hLead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ShapeFont::charToFrameNum(char c) const {
|
||||
if (_crusaderCharMap) {
|
||||
if (c < 41)
|
||||
// ( and ) are combined into a single shape
|
||||
return c;
|
||||
// weirdly X and Y are swapped in both upper and lowercase
|
||||
else if (c == 'X')
|
||||
return 'X';
|
||||
else if (c == 'Y')
|
||||
return 'W';
|
||||
else if (c < 96)
|
||||
return c - 1;
|
||||
else if (c == 96)
|
||||
// no backquote char
|
||||
return charToFrameNum('\'');
|
||||
else if (c == 'x')
|
||||
return 'w';
|
||||
else if (c == 'y')
|
||||
return 'v';
|
||||
else
|
||||
return c - 2;
|
||||
} else {
|
||||
return static_cast<unsigned char>(c);
|
||||
}
|
||||
}
|
||||
|
||||
RenderedText *ShapeFont::renderText(const Std::string &text,
|
||||
unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align,
|
||||
bool u8specials, bool pagebreaks,
|
||||
Std::string::size_type cursor) {
|
||||
int32 resultwidth, resultheight;
|
||||
Std::list<PositionedText> lines;
|
||||
lines = typesetText<Traits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultwidth, resultheight, cursor);
|
||||
|
||||
return new ShapeRenderedText(lines, resultwidth, resultheight,
|
||||
getVlead(), this);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
77
engines/ultima/ultima8/gfx/fonts/shape_font.h
Normal file
77
engines/ultima/ultima8/gfx/fonts/shape_font.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_SHAPEFONT_H
|
||||
#define ULTIMA8_GFX_FONTS_SHAPEFONT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFont : public Font, public Shape {
|
||||
int _height;
|
||||
int _baseLine;
|
||||
int _vLead;
|
||||
int _hLead;
|
||||
bool _crusaderCharMap;
|
||||
|
||||
public:
|
||||
ShapeFont(const uint8 *data, uint32 size, const ConvertShapeFormat *format,
|
||||
const uint16 flexId, const uint32 shapenum);
|
||||
~ShapeFont() override;
|
||||
|
||||
int getHeight() override;
|
||||
int getBaseline() override;
|
||||
int getBaselineSkip() override;
|
||||
|
||||
int getWidth(char c);
|
||||
int getVlead() const {
|
||||
return _vLead;
|
||||
}
|
||||
int getHlead() const {
|
||||
return _hLead;
|
||||
}
|
||||
|
||||
void setVLead(int vl) {
|
||||
_vLead = vl;
|
||||
}
|
||||
void setHLead(int hl) {
|
||||
_hLead = hl;
|
||||
}
|
||||
|
||||
int charToFrameNum(char c) const;
|
||||
|
||||
void getStringSize(const Std::string &text,
|
||||
int32 &width, int32 &height) override;
|
||||
|
||||
RenderedText *renderText(const Std::string &text,
|
||||
unsigned int &remaining, int32 width = 0, int32 height = 0,
|
||||
TextAlign align = TEXT_LEFT, bool u8specials = false,
|
||||
bool pagebreaks = false,
|
||||
Std::string::size_type cursor = Std::string::npos) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
102
engines/ultima/ultima8/gfx/fonts/shape_rendered_text.cpp
Normal file
102
engines/ultima/ultima8/gfx/fonts/shape_rendered_text.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/gfx/fonts/shape_rendered_text.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/shape_font.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ShapeRenderedText::ShapeRenderedText(const Std::list<PositionedText> &lines,
|
||||
int width, int height, int vLead,
|
||||
ShapeFont *font)
|
||||
: _lines(lines), _font(font) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_vLead = vLead;
|
||||
}
|
||||
|
||||
ShapeRenderedText::~ShapeRenderedText() {
|
||||
}
|
||||
|
||||
void ShapeRenderedText::draw(RenderSurface *surface, int x, int y, bool /*destmasked*/) {
|
||||
// TODO support masking here???
|
||||
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
Std::list<PositionedText>::const_iterator iter;
|
||||
|
||||
surface->BeginPainting();
|
||||
|
||||
for (const auto &line : _lines) {
|
||||
int line_x = x + line._dims.left;
|
||||
int line_y = y + line._dims.top;
|
||||
|
||||
size_t textsize = line._text.size();
|
||||
|
||||
for (size_t i = 0; i < textsize; ++i) {
|
||||
surface->Paint(_font, _font->charToFrameNum(line._text[i]),
|
||||
line_x, line_y);
|
||||
|
||||
if (i == line._cursor) {
|
||||
surface->fill32(color, line_x, line_y - _font->getBaseline(),
|
||||
1, line._dims.height());
|
||||
}
|
||||
|
||||
line_x += _font->getWidth(line._text[i]) - _font->getHlead();
|
||||
}
|
||||
|
||||
if (line._cursor == textsize) {
|
||||
surface->fill32(color, line_x, line_y - _font->getBaseline(),
|
||||
1, line._dims.height());
|
||||
}
|
||||
}
|
||||
|
||||
surface->EndPainting();
|
||||
}
|
||||
|
||||
void ShapeRenderedText::drawBlended(RenderSurface *surface, int x, int y,
|
||||
uint32 col, bool /*destmasked*/) {
|
||||
// TODO Support masking here ????
|
||||
|
||||
Std::list<PositionedText>::const_iterator iter;
|
||||
|
||||
for (const auto &line : _lines) {
|
||||
int line_x = x + line._dims.left;
|
||||
int line_y = y + line._dims.top;
|
||||
|
||||
size_t textsize = line._text.size();
|
||||
|
||||
for (size_t i = 0; i < textsize; ++i) {
|
||||
surface->PaintHighlight(_font,
|
||||
static_cast<unsigned char>(line._text[i]),
|
||||
line_x, line_y, false, false, col);
|
||||
line_x += _font->getWidth(line._text[i]) - _font->getHlead();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
50
engines/ultima/ultima8/gfx/fonts/shape_rendered_text.h
Normal file
50
engines/ultima/ultima8/gfx/fonts/shape_rendered_text.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_SHAPERENDEREDTEXT_H
|
||||
#define ULTIMA8_GFX_FONTS_SHAPERENDEREDTEXT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFont;
|
||||
|
||||
class ShapeRenderedText : public RenderedText {
|
||||
public:
|
||||
ShapeRenderedText(const Std::list<PositionedText> &lines,
|
||||
int width, int height, int vlead, ShapeFont *font);
|
||||
~ShapeRenderedText() override;
|
||||
|
||||
void draw(RenderSurface *surface, int x, int y, bool destmasked = false) override;
|
||||
void drawBlended(RenderSurface *surface, int x, int y, uint32 col, bool destmasked = false) override;
|
||||
|
||||
protected:
|
||||
Std::list<PositionedText> _lines;
|
||||
ShapeFont *_font;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
299
engines/ultima/ultima8/gfx/fonts/tt_font.cpp
Normal file
299
engines/ultima/ultima8/gfx/fonts/tt_font.cpp
Normal file
@@ -0,0 +1,299 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/tt_font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/ttf_rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
|
||||
//include iomanip
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// various unicode characters which look like small black circles
|
||||
static const uint16 BULLETS[] = { 0x2022, 0x30FB, 0x25CF, 0 };
|
||||
|
||||
TTFont::TTFont(Graphics::Font *font, uint32 rgb, int borderSize,
|
||||
bool antiAliased, bool SJIS) :
|
||||
_borderSize(borderSize), _ttfFont(font), _antiAliased(antiAliased), _SJIS(SJIS),
|
||||
_PF_RGBA(Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)) {
|
||||
_color = _PF_RGBA.RGBToColor((rgb >> 16) & 0xFF, (rgb >> 8) & 0xff, rgb & 0xff);
|
||||
|
||||
_bullet = 0;
|
||||
// scan for a character to use as a conversation option _bullet
|
||||
for (int i = 0; BULLETS[i]; ++i) {
|
||||
Common::Rect box = font->getBoundingBox(BULLETS[i]);
|
||||
|
||||
if (!box.isEmpty()) {
|
||||
_bullet = BULLETS[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_bullet == 0) {
|
||||
_bullet = '*';
|
||||
}
|
||||
}
|
||||
|
||||
TTFont::~TTFont() {
|
||||
|
||||
}
|
||||
|
||||
int TTFont::getHeight() {
|
||||
return _ttfFont->getFontHeight() + 2 * _borderSize; // constant (border)
|
||||
}
|
||||
|
||||
int TTFont::getBaseline() {
|
||||
Common::Rect box = _ttfFont->getBoundingBox('W');
|
||||
return box.bottom;
|
||||
}
|
||||
|
||||
int TTFont::getBaselineSkip() {
|
||||
// TODO: Come up with something more generic than just hardcoding 2 pixel line separation
|
||||
return getHeight() + 2;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static Common::U32String toUnicode(const Std::string &text, uint16 bullet) {
|
||||
Std::string::size_type len = T::length(text);
|
||||
Common::U32String result = Common::U32String(text.c_str(), len);
|
||||
|
||||
Std::string::const_iterator iter = text.begin();
|
||||
for (uint idx = 0; idx < len; ++idx) {
|
||||
uint32 u = T::unicode(iter);
|
||||
if (u == '@') {
|
||||
result.setChar(bullet, idx);
|
||||
} else {
|
||||
result.setChar(u, idx);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TTFont::getStringSize(const Std::string &text, int32 &width, int32 &height) {
|
||||
// convert to unicode
|
||||
Common::U32String unicodeText;
|
||||
if (!_SJIS)
|
||||
unicodeText = toUnicode<Traits>(text, _bullet);
|
||||
else
|
||||
unicodeText = toUnicode<SJISTraits>(text, _bullet);
|
||||
|
||||
width = _ttfFont->getStringWidth(unicodeText);
|
||||
height = _ttfFont->getFontHeight();
|
||||
|
||||
width += 2 * _borderSize;
|
||||
height += 2 * _borderSize;
|
||||
}
|
||||
|
||||
void TTFont::getTextSize(const Std::string &text,
|
||||
int32 &resultWidth, int32 &resultHeight,
|
||||
unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align,
|
||||
bool u8specials, bool pagebreaks) {
|
||||
Std::list<PositionedText> tmp;
|
||||
if (!_SJIS)
|
||||
tmp = typesetText<Traits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultWidth, resultHeight);
|
||||
else
|
||||
tmp = typesetText<SJISTraits>(this, text, remaining,
|
||||
width, height, align, u8specials, pagebreaks,
|
||||
resultWidth, resultHeight);
|
||||
}
|
||||
|
||||
|
||||
void TTFont::addTextBorder(Graphics::ManagedSurface &textSurf, uint32 *texBuf, const Common::Rect32 &dims, int32 resultWidth, int32 resultHeight, uint32 borderColor) {
|
||||
uint8 bA, bR, bG, bB;
|
||||
_PF_RGBA.colorToARGB(borderColor, bA, bR, bG, bB);
|
||||
|
||||
int sqrSize = _borderSize * _borderSize;
|
||||
int sqrEdge = (_borderSize + 1) * (_borderSize + 1);
|
||||
|
||||
for (int y = 0; y < textSurf.h; y++) {
|
||||
const byte* surfrow = (const byte*)textSurf.getBasePtr(0, y);
|
||||
|
||||
for (int x = 0; x < textSurf.w; x++) {
|
||||
if (_antiAliased) {
|
||||
uint32 sColor = *((const uint32 *)(surfrow + x * 4));
|
||||
uint8 sR, sG, sB, sA;
|
||||
_PF_RGBA.colorToARGB(sColor, sA, sR, sG, sB);
|
||||
|
||||
if (sA == 0x00)
|
||||
continue;
|
||||
|
||||
for (int dx = -_borderSize; dx <= _borderSize; dx++) {
|
||||
for (int dy = -_borderSize; dy <= _borderSize; dy++) {
|
||||
int tx = dims.left + x + _borderSize + dx;
|
||||
int ty = dims.top + y + _borderSize + dy;
|
||||
if (tx >= 0 && tx < resultWidth && ty >= 0 && ty < resultHeight) {
|
||||
uint32 dColor = texBuf[ty * resultWidth + tx];
|
||||
if (borderColor != dColor) {
|
||||
int sqrDist = (dx * dx) + (dy * dy);
|
||||
if (sqrDist < sqrSize) {
|
||||
texBuf[ty * resultWidth + tx] = borderColor;
|
||||
}
|
||||
else if (sqrDist < sqrEdge) {
|
||||
// Blend border color at source intensity with destination
|
||||
uint8 dA, dR, dG, dB;
|
||||
_PF_RGBA.colorToARGB(dColor, dA, dR, dG, dB);
|
||||
|
||||
double bAlpha = (double)bA / 255.0;
|
||||
double sAlpha = (double)sA / 255.0;
|
||||
double dAlpha = (double)dA / 255.0;
|
||||
dAlpha *= (1.0 - sAlpha);
|
||||
|
||||
dR = static_cast<uint8>((bR * sAlpha + dR * dAlpha) / (sAlpha + dAlpha));
|
||||
dG = static_cast<uint8>((bG * sAlpha + dG * dAlpha) / (sAlpha + dAlpha));
|
||||
dB = static_cast<uint8>((bB * sAlpha + dB * dAlpha) / (sAlpha + dAlpha));
|
||||
dA = static_cast<uint8>(255. * bAlpha * (sAlpha + dAlpha));
|
||||
|
||||
texBuf[ty * resultWidth + tx] = _PF_RGBA.ARGBToColor(dA, dR, dG, dB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (surfrow[x] == 1) {
|
||||
for (int dx = -_borderSize; dx <= _borderSize; dx++) {
|
||||
for (int dy = -_borderSize; dy <= _borderSize; dy++) {
|
||||
int tx = dims.left + x + _borderSize + dx;
|
||||
int ty = dims.top + y + _borderSize + dy;
|
||||
if (tx >= 0 && tx < resultWidth && ty >= 0 && ty < resultHeight) {
|
||||
int sqrDist = (dx * dx) + (dy * dy);
|
||||
if (sqrDist < sqrEdge) {
|
||||
texBuf[ty * resultWidth + tx] = borderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenderedText *TTFont::renderText(const Std::string &text, unsigned int &remaining,
|
||||
int32 width, int32 height, TextAlign align, bool u8specials, bool pagebreaks,
|
||||
Std::string::size_type cursor) {
|
||||
int32 resultWidth, resultHeight, lineHeight;
|
||||
Std::list<PositionedText> lines;
|
||||
if (!_SJIS)
|
||||
lines = typesetText<Traits>(this, text, remaining, width, height, align, u8specials, pagebreaks,
|
||||
resultWidth, resultHeight, cursor);
|
||||
else
|
||||
lines = typesetText<SJISTraits>(this, text, remaining, width, height, align, u8specials, pagebreaks,
|
||||
resultWidth, resultHeight, cursor);
|
||||
lineHeight = _ttfFont->getFontHeight();
|
||||
|
||||
uint32 borderColor = _PF_RGBA.ARGBToColor(0xFF, 0x00, 0x00, 0x00);
|
||||
|
||||
Graphics::ManagedSurface *texture = new Graphics::ManagedSurface(resultWidth, resultHeight, _PF_RGBA);
|
||||
uint32 *texBuf = (uint32 *)texture->getPixels();
|
||||
|
||||
for (const auto &line : lines) {
|
||||
// convert to unicode
|
||||
Common::U32String unicodeText;
|
||||
if (!_SJIS)
|
||||
unicodeText = toUnicode<Traits>(line._text, _bullet);
|
||||
else
|
||||
unicodeText = toUnicode<SJISTraits>(line._text, _bullet);
|
||||
|
||||
// Create a surface and render the text
|
||||
Graphics::ManagedSurface textSurf;
|
||||
|
||||
if (!_antiAliased) {
|
||||
// When not in antialiased mode, use a paletted surface where '1' is
|
||||
// used for pixels of the text
|
||||
textSurf.create(resultWidth, lineHeight, Graphics::PixelFormat::createFormatCLUT8());
|
||||
_ttfFont->drawString(&textSurf, unicodeText, 0, 0, resultWidth, 1);
|
||||
} else {
|
||||
// Use a high color surface with the specified _color color for text
|
||||
textSurf.create(resultWidth, lineHeight, _PF_RGBA);
|
||||
_ttfFont->drawString(&textSurf, unicodeText, 0, 0, resultWidth, _color);
|
||||
};
|
||||
|
||||
// Add border within radius. Pixels on the edge are alpha blended if antialiased
|
||||
if (_borderSize > 0) {
|
||||
addTextBorder(textSurf, texBuf, line._dims, resultWidth, resultHeight, borderColor);
|
||||
}
|
||||
|
||||
// render the text surface into our texture buffer
|
||||
for (int y = 0; y < textSurf.h; y++) {
|
||||
const byte *surfrow = (const byte *)textSurf.getBasePtr(0, y);
|
||||
|
||||
int ty = line._dims.top + y + _borderSize;
|
||||
for (int x = 0; x < textSurf.w; x++) {
|
||||
int tx = line._dims.left + x + _borderSize;
|
||||
if (_antiAliased) {
|
||||
uint32 sColor = *((const uint32 *)(surfrow + x * 4));
|
||||
uint8 sR, sG, sB, sA;
|
||||
_PF_RGBA.colorToARGB(sColor, sA, sR, sG, sB);
|
||||
|
||||
if (sA == 0xFF) {
|
||||
texBuf[ty * resultWidth + tx] = sColor;
|
||||
}
|
||||
else if (sA != 0x00) {
|
||||
// Blend color with destination
|
||||
int32 dColor = texBuf[ty * resultWidth + tx];
|
||||
uint8 dA, dR, dG, dB;
|
||||
_PF_RGBA.colorToARGB(dColor, dA, dR, dG, dB);
|
||||
|
||||
double sAlpha = (double)sA / 255.0;
|
||||
double dAlpha = (double)dA / 255.0;
|
||||
dAlpha *= (1.0 - sAlpha);
|
||||
|
||||
dR = static_cast<uint8>((sR * sAlpha + dR * dAlpha) / (sAlpha + dAlpha));
|
||||
dG = static_cast<uint8>((sG * sAlpha + dG * dAlpha) / (sAlpha + dAlpha));
|
||||
dB = static_cast<uint8>((sB * sAlpha + dB * dAlpha) / (sAlpha + dAlpha));
|
||||
dA = static_cast<uint8>(255. * (sAlpha + dAlpha));
|
||||
|
||||
texBuf[ty * resultWidth + tx] = _PF_RGBA.ARGBToColor(dA, dR, dG, dB);
|
||||
}
|
||||
}
|
||||
else if (surfrow[x] == 1) {
|
||||
texBuf[ty * resultWidth + tx] = _color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (line._cursor != Std::string::npos) {
|
||||
assert(line._cursor <= line._text.size());
|
||||
unicodeText = unicodeText.substr(0, line._cursor);
|
||||
|
||||
int w = _ttfFont->getStringWidth(unicodeText);
|
||||
|
||||
for (int y = 0; y < line._dims.height(); y++) {
|
||||
int tx = line._dims.left + w + _borderSize;
|
||||
int ty = line._dims.top + y;
|
||||
texBuf[ty * resultWidth + tx] = borderColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new TTFRenderedText(texture, resultWidth, resultHeight,
|
||||
getBaselineSkip() - getHeight(), getBaseline(), isAntialiased());
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
76
engines/ultima/ultima8/gfx/fonts/tt_font.h
Normal file
76
engines/ultima/ultima8/gfx/fonts/tt_font.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_TTFONT_H
|
||||
#define ULTIMA8_GFX_FONTS_TTFONT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TTFont : public Font {
|
||||
public:
|
||||
TTFont(Graphics::Font *font, uint32 rgb, int bordersize,
|
||||
bool antiAliased, bool SJIS);
|
||||
~TTFont() override;
|
||||
|
||||
int getHeight() override;
|
||||
int getBaseline() override;
|
||||
int getBaselineSkip() override;
|
||||
|
||||
bool isAntialiased() {
|
||||
return _antiAliased;
|
||||
}
|
||||
|
||||
void getStringSize(const Std::string &text,
|
||||
int32 &width, int32 &height) override;
|
||||
|
||||
void getTextSize(const Std::string &text,
|
||||
int32 &resultwidth, int32 &resultheight, unsigned int &remaining,
|
||||
int32 width = 0, int32 height = 0, TextAlign align = TEXT_LEFT,
|
||||
bool u8specials = false, bool pagebreaks = false) override;
|
||||
|
||||
RenderedText *renderText(const Std::string &text,
|
||||
unsigned int &remaining, int32 width = 0, int32 height = 0,
|
||||
TextAlign align = TEXT_LEFT, bool u8specials = false,
|
||||
bool pagebreaks = false,
|
||||
Std::string::size_type cursor = Std::string::npos) override;
|
||||
|
||||
protected:
|
||||
Graphics::Font *_ttfFont;
|
||||
uint32 _color;
|
||||
int _borderSize;
|
||||
bool _antiAliased;
|
||||
bool _SJIS;
|
||||
Graphics::PixelFormat _PF_RGBA;
|
||||
|
||||
uint16 _bullet;
|
||||
|
||||
void addTextBorder(Graphics::ManagedSurface &textSurf, uint32 *texBuf, const Common::Rect32 &dims, int32 resultWidth, int32 resultHeight, uint32 borderColor);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
61
engines/ultima/ultima8/gfx/fonts/ttf_rendered_text.cpp
Normal file
61
engines/ultima/ultima8/gfx/fonts/ttf_rendered_text.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
#include "ultima/ultima8/gfx/fonts/ttf_rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/tt_font.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
TTFRenderedText::TTFRenderedText(Graphics::ManagedSurface *texture, int width, int height,
|
||||
int vLead, int baseline, bool antiAliased) : _texture(texture), _baseline(baseline), _antiAliased(antiAliased) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_vLead = vLead;
|
||||
}
|
||||
|
||||
TTFRenderedText::~TTFRenderedText() {
|
||||
delete _texture;
|
||||
}
|
||||
|
||||
void TTFRenderedText::draw(RenderSurface *surface, int x, int y, bool destmasked) {
|
||||
if (!_width)
|
||||
return;
|
||||
Common::Rect srcRect(_width, _height);
|
||||
if (!destmasked)
|
||||
surface->Blit(*_texture, srcRect, x, y - _baseline, _antiAliased);
|
||||
else
|
||||
surface->MaskedBlit(*_texture, srcRect, x, y - _baseline, 0, _antiAliased);
|
||||
}
|
||||
|
||||
void TTFRenderedText::drawBlended(RenderSurface *surface, int x, int y,
|
||||
uint32 col, bool destmasked) {
|
||||
Common::Rect srcRect(_width, _height);
|
||||
if (!destmasked)
|
||||
surface->FadedBlit(*_texture, srcRect, x, y - _baseline, col, _antiAliased);
|
||||
else
|
||||
surface->MaskedBlit(*_texture, srcRect, x, y - _baseline, col, _antiAliased);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
55
engines/ultima/ultima8/gfx/fonts/ttf_rendered_text.h
Normal file
55
engines/ultima/ultima8/gfx/fonts/ttf_rendered_text.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FONTS_SHAPERENDEREDTEXT_H
|
||||
#define ULTIMA8_GFX_FONTS_SHAPERENDEREDTEXT_H
|
||||
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TTFont;
|
||||
class Texture;
|
||||
|
||||
class TTFRenderedText : public RenderedText {
|
||||
public:
|
||||
TTFRenderedText(Graphics::ManagedSurface *texture, int width, int height, int vlead,
|
||||
int baseline, bool antiAliased);
|
||||
~TTFRenderedText() override;
|
||||
|
||||
void draw(RenderSurface *surface, int x, int y,
|
||||
bool destmasked = false) override;
|
||||
void drawBlended(RenderSurface *surface, int x, int y, uint32 col,
|
||||
bool destmasked = false) override;
|
||||
|
||||
protected:
|
||||
Graphics::ManagedSurface *_texture;
|
||||
int _baseline;
|
||||
bool _antiAliased;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
41
engines/ultima/ultima8/gfx/frame_id.cpp
Normal file
41
engines/ultima/ultima8/gfx/frame_id.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/* 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 "ultima/ultima8/gfx/frame_id.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
void FrameID::save(Common::WriteStream *ws) {
|
||||
ws->writeUint16LE(_flexId);
|
||||
ws->writeUint32LE(_shapeNum);
|
||||
ws->writeUint32LE(_frameNum);
|
||||
}
|
||||
|
||||
bool FrameID::load(Common::ReadStream *rs) {
|
||||
_flexId = rs->readUint16LE();
|
||||
_shapeNum = rs->readUint32LE();
|
||||
_frameNum = rs->readUint32LE();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
47
engines/ultima/ultima8/gfx/frame_id.h
Normal file
47
engines/ultima/ultima8/gfx/frame_id.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_FRAMEID_H
|
||||
#define ULTIMA8_GFX_FRAMEID_H
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
struct FrameID {
|
||||
uint16 _flexId;
|
||||
uint32 _shapeNum;
|
||||
uint32 _frameNum;
|
||||
|
||||
FrameID() : _flexId(0), _shapeNum(0), _frameNum(0) { }
|
||||
FrameID(uint16 flex, uint32 shape, uint32 frame)
|
||||
: _flexId(flex), _shapeNum(shape), _frameNum(frame) {
|
||||
}
|
||||
|
||||
void save(Common::WriteStream *ws);
|
||||
bool load(Common::ReadStream *rs);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
53
engines/ultima/ultima8/gfx/gump_shape_archive.cpp
Normal file
53
engines/ultima/ultima8/gfx/gump_shape_archive.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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 "ultima/ultima8/gfx/gump_shape_archive.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
GumpShapeArchive::~GumpShapeArchive() {
|
||||
for (unsigned int i = 0; i < _gumpItemArea.size(); ++i)
|
||||
delete _gumpItemArea[i];
|
||||
}
|
||||
|
||||
void GumpShapeArchive::loadGumpage(Common::SeekableReadStream *rs) {
|
||||
unsigned int total = rs->size() / 8;
|
||||
_gumpItemArea.resize(total + 1);
|
||||
for (unsigned int i = 1; i <= total; ++i) {
|
||||
int x1, y1, x2, y2;
|
||||
x1 = static_cast<int16>(rs->readUint16LE());
|
||||
y1 = static_cast<int16>(rs->readUint16LE());
|
||||
x2 = static_cast<int16>(rs->readUint16LE());
|
||||
y2 = static_cast<int16>(rs->readUint16LE());
|
||||
_gumpItemArea[i] = new Common::Rect32(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
Common::Rect32 *GumpShapeArchive::getGumpItemArea(uint32 shapenum) {
|
||||
if (shapenum >= _gumpItemArea.size())
|
||||
return nullptr;
|
||||
return _gumpItemArea[shapenum];
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
52
engines/ultima/ultima8/gfx/gump_shape_archive.h
Normal file
52
engines/ultima/ultima8/gfx/gump_shape_archive.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_GUMPSHAPEARCHIVE_H
|
||||
#define ULTIMA8_GFX_GUMPSHAPEARCHIVE_H
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class GumpShapeArchive : public ShapeArchive {
|
||||
public:
|
||||
GumpShapeArchive(uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(id, pal, format) { }
|
||||
GumpShapeArchive(Common::SeekableReadStream *rs, uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(rs, id, pal, format) { }
|
||||
|
||||
~GumpShapeArchive() override;
|
||||
|
||||
void loadGumpage(Common::SeekableReadStream *rs);
|
||||
Common::Rect32 *getGumpItemArea(uint32 shapenum);
|
||||
|
||||
protected:
|
||||
Std::vector<Common::Rect32 *> _gumpItemArea;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
113
engines/ultima/ultima8/gfx/inverter_process.cpp
Normal file
113
engines/ultima/ultima8/gfx/inverter_process.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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 "ultima/ultima8/gfx/inverter_process.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
static unsigned int states[] = { 0, 8, 63, 211, 493, 945, 1594, 2459, 3552,
|
||||
4870, 6406, 8139, 10042, 12078, 14207, 16384,
|
||||
18561, 20690, 22726, 24629, 26362, 27898,
|
||||
29216, 30308, 31174, 31823, 32274, 32556,
|
||||
32704, 32760, 32768,
|
||||
32775, 32831, 32979, 33261, 33713, 34362,
|
||||
35227, 36320, 37638, 39174, 40907, 42810,
|
||||
44846, 46975, 49152, 51328, 53457, 55494,
|
||||
57396, 59129, 60665, 61984, 63076, 63942,
|
||||
64591, 65042, 65324, 65472, 65528, 65536
|
||||
};
|
||||
|
||||
InverterProcess *InverterProcess::_inverter = nullptr;
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(InverterProcess)
|
||||
|
||||
InverterProcess::InverterProcess()
|
||||
: Process(), _targetState(0) {
|
||||
|
||||
}
|
||||
|
||||
InverterProcess::InverterProcess(unsigned int target)
|
||||
: Process(), _targetState(target) {
|
||||
}
|
||||
|
||||
InverterProcess::~InverterProcess(void) {
|
||||
if (_inverter == this)
|
||||
_inverter = nullptr;
|
||||
}
|
||||
|
||||
void InverterProcess::run() {
|
||||
Ultima8Engine *app = Ultima8Engine::get_instance();
|
||||
|
||||
unsigned int state = app->getInversion();
|
||||
if (state == _targetState) {
|
||||
terminate();
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
while (states[i] <= state) i++;
|
||||
app->setInversion(states[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void InverterProcess::saveData(Common::WriteStream *ws) {
|
||||
Process::saveData(ws);
|
||||
|
||||
ws->writeUint16LE(static_cast<uint16>(_targetState));
|
||||
}
|
||||
|
||||
bool InverterProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
_targetState = rs->readUint16LE();
|
||||
|
||||
_inverter = this; //static
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
ProcId InverterProcess::invertScreen() {
|
||||
if (_inverter) {
|
||||
if (_inverter->_targetState == 0)
|
||||
_inverter->setTarget(0x8000);
|
||||
else
|
||||
_inverter->setTarget(0);
|
||||
return _inverter->getPid();
|
||||
} else {
|
||||
unsigned int target = 0x8000;
|
||||
if (Ultima8Engine::get_instance()->isInverted()) target = 0;
|
||||
_inverter = new InverterProcess(target);
|
||||
return Kernel::get_instance()->addProcess(_inverter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32 InverterProcess::I_invertScreen(const uint8 *args,
|
||||
unsigned int /*argsize*/) {
|
||||
return invertScreen();
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gfx/inverter_process.h
Normal file
63
engines/ultima/ultima8/gfx/inverter_process.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_INVERTERPROCESS_H
|
||||
#define ULTIMA8_GFX_INVERTERPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/** The process to tear and flip the screen, triggered by some game events in U8 */
|
||||
class InverterProcess : public Process {
|
||||
public:
|
||||
InverterProcess();
|
||||
InverterProcess(unsigned int targetstate);
|
||||
~InverterProcess() override;
|
||||
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
|
||||
void setTarget(unsigned int target) {
|
||||
_targetState = target;
|
||||
}
|
||||
|
||||
void run() override;
|
||||
|
||||
static ProcId invertScreen();
|
||||
|
||||
INTRINSIC(I_invertScreen);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
|
||||
protected:
|
||||
static InverterProcess *_inverter;
|
||||
unsigned int _targetState;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
84
engines/ultima/ultima8/gfx/main_shape_archive.cpp
Normal file
84
engines/ultima/ultima8/gfx/main_shape_archive.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/type_flags.h"
|
||||
#include "ultima/ultima8/gfx/anim_dat.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
MainShapeArchive::~MainShapeArchive() {
|
||||
if (_typeFlags) {
|
||||
delete _typeFlags;
|
||||
}
|
||||
|
||||
if (_animDat) {
|
||||
delete _animDat;
|
||||
}
|
||||
}
|
||||
|
||||
void MainShapeArchive::loadTypeFlags(Common::SeekableReadStream *rs) {
|
||||
if (_typeFlags) {
|
||||
delete _typeFlags;
|
||||
_typeFlags = nullptr;
|
||||
}
|
||||
|
||||
_typeFlags = new TypeFlags;
|
||||
_typeFlags->load(rs);
|
||||
}
|
||||
|
||||
void MainShapeArchive::loadDamageDat(Common::SeekableReadStream *rs) {
|
||||
assert(_typeFlags);
|
||||
_typeFlags->loadDamageDat(rs);
|
||||
}
|
||||
|
||||
const ShapeInfo *MainShapeArchive::getShapeInfo(uint32 shapenum) {
|
||||
assert(_typeFlags);
|
||||
|
||||
return _typeFlags->getShapeInfo(shapenum);
|
||||
}
|
||||
|
||||
void MainShapeArchive::loadAnimDat(Common::SeekableReadStream *rs) {
|
||||
if (_animDat) {
|
||||
delete _animDat;
|
||||
_animDat = nullptr;
|
||||
}
|
||||
|
||||
_animDat = new AnimDat;
|
||||
_animDat->load(rs);
|
||||
}
|
||||
|
||||
const ActorAnim *MainShapeArchive::getAnim(uint32 shape) const {
|
||||
assert(_animDat);
|
||||
|
||||
return _animDat->getAnim(shape);
|
||||
}
|
||||
|
||||
const AnimAction *MainShapeArchive::getAnim(uint32 shape, uint32 action) const {
|
||||
assert(_animDat);
|
||||
|
||||
return _animDat->getAnim(shape, action);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
63
engines/ultima/ultima8/gfx/main_shape_archive.h
Normal file
63
engines/ultima/ultima8/gfx/main_shape_archive.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_MAINSHAPEARCHIVE_H
|
||||
#define ULTIMA8_GFX_MAINSHAPEARCHIVE_H
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TypeFlags;
|
||||
class ShapeInfo;
|
||||
class AnimDat;
|
||||
class ActorAnim;
|
||||
class AnimAction;
|
||||
|
||||
class MainShapeArchive : public ShapeArchive {
|
||||
public:
|
||||
MainShapeArchive(uint16 id, const Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(id, pal, format), _typeFlags(0), _animDat(0) { }
|
||||
MainShapeArchive(Common::SeekableReadStream *rs, uint16 id, const Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(rs, id, pal, format), _typeFlags(0), _animDat(0) { }
|
||||
|
||||
~MainShapeArchive() override;
|
||||
|
||||
void loadTypeFlags(Common::SeekableReadStream *rs);
|
||||
void loadDamageDat(Common::SeekableReadStream *rs);
|
||||
const ShapeInfo *getShapeInfo(uint32 shapenum);
|
||||
|
||||
void loadAnimDat(Common::SeekableReadStream *rs);
|
||||
const ActorAnim *getAnim(uint32 shape) const;
|
||||
const AnimAction *getAnim(uint32 shape, uint32 action) const;
|
||||
|
||||
protected:
|
||||
TypeFlags *_typeFlags;
|
||||
AnimDat *_animDat;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
56
engines/ultima/ultima8/gfx/mouse_shape_archive.h
Normal file
56
engines/ultima/ultima8/gfx/mouse_shape_archive.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_MOUSESHAPEARCHIVE_H
|
||||
#define ULTIMA8_GFX_MOUSESHAPEARCHIVE_H
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
// Fake archive class for mouse shape in the shape viewer
|
||||
// TODO - consider using this in GameData and owning the shape
|
||||
class MouseShapeArchive : public ShapeArchive {
|
||||
public:
|
||||
MouseShapeArchive(uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(id, pal, format) {}
|
||||
MouseShapeArchive(Shape *shape, uint16 id, Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: ShapeArchive(id, pal, format) {
|
||||
_shapes.push_back(shape);
|
||||
_count = 1;
|
||||
}
|
||||
~MouseShapeArchive() override {
|
||||
_shapes.clear();
|
||||
}
|
||||
|
||||
void cache(uint32 shapenum) override {}
|
||||
void uncache(uint32 shapenum) override {}
|
||||
bool isCached(uint32 shapenum) const override { return true; }
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
48
engines/ultima/ultima8/gfx/movie_player.h
Normal file
48
engines/ultima/ultima8/gfx/movie_player.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_MOVIEPLAYER_H
|
||||
#define ULTIMA8_GFX_MOVIEPLAYER_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RenderSurface;
|
||||
|
||||
class MoviePlayer {
|
||||
public:
|
||||
MoviePlayer() {};
|
||||
virtual ~MoviePlayer() {};
|
||||
|
||||
virtual void run() = 0;
|
||||
virtual void paint(RenderSurface *surf, int lerp) = 0;
|
||||
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual bool isPlaying() const = 0;
|
||||
virtual void setOffset(int x, int y) {};
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
62
engines/ultima/ultima8/gfx/pal_transforms.h
Normal file
62
engines/ultima/ultima8/gfx/pal_transforms.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_PAL_TRANSFORMS_H
|
||||
#define ULTIMA8_GFX_PAL_TRANSFORMS_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
enum PalTransforms {
|
||||
// Normal untransformed palette
|
||||
Transform_None = 0,
|
||||
|
||||
// O[i] = I[r]*0.375 + I[g]*0.5 + I[b]*0.125;
|
||||
Transform_Greyscale = 1,
|
||||
|
||||
// O[r] = 0;
|
||||
Transform_NoRed = 2,
|
||||
|
||||
// O[i] = (I[i] + Grey)*0.25 + 0.1875;
|
||||
Transform_RainStorm = 3,
|
||||
|
||||
// O[r] = (I[r] + Grey)*0.5 + 0.1875;
|
||||
// O[g] = I[g]*0.5 + Grey*0.25;
|
||||
// O[b] = I[b]*0.5;
|
||||
Transform_FireStorm = 4,
|
||||
|
||||
// O[i] = I[i]*2 -Grey;
|
||||
Transform_Saturate = 5,
|
||||
|
||||
// O[g] = I[r]; O[b] = I[g]; O[r] = I[b];
|
||||
Transform_GBR = 6,
|
||||
|
||||
// O[b] = I[r]; O[r] = I[g]; O[g] = I[b];
|
||||
Transform_BRG = 7,
|
||||
|
||||
// Any value beyond this is invalid in savegames.
|
||||
Transform_Invalid = 8
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
179
engines/ultima/ultima8/gfx/palette.cpp
Normal file
179
engines/ultima/ultima8/gfx/palette.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/* 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 "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
void Palette::load(Common::ReadStream &rs, Common::ReadStream &xformrs) {
|
||||
load(rs);
|
||||
for (int i = 0; i < 256; i++)
|
||||
_xform_untransformed[i] = xformrs.readUint32LE();
|
||||
}
|
||||
|
||||
void Palette::load(Common::ReadStream &rs) {
|
||||
int i;
|
||||
byte raw[768];
|
||||
rs.read(raw, 768);
|
||||
|
||||
// convert from 0-63 to 0-255 _palette
|
||||
for (i = 0; i < 256; i++) {
|
||||
set(i, PALETTE_6BIT_TO_8BIT(raw[i * 3]), PALETTE_6BIT_TO_8BIT(raw[i * 3 + 1]), PALETTE_6BIT_TO_8BIT(raw[i * 3 + 2]));
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
_xform_untransformed[i] = 0;
|
||||
|
||||
// Setup the transformation _matrix
|
||||
_matrix[0] = 0x800;
|
||||
_matrix[1] = 0;
|
||||
_matrix[2] = 0;
|
||||
_matrix[3] = 0;
|
||||
_matrix[4] = 0;
|
||||
_matrix[5] = 0x800;
|
||||
_matrix[6] = 0;
|
||||
_matrix[7] = 0;
|
||||
_matrix[8] = 0;
|
||||
_matrix[9] = 0;
|
||||
_matrix[10] = 0x800;
|
||||
_matrix[11] = 0;
|
||||
|
||||
_transform = Transform_None;
|
||||
}
|
||||
|
||||
void Palette::transformRGB(int &r_, int &g_, int &b_) const {
|
||||
const int r = r_;
|
||||
const int g = g_;
|
||||
const int b = b_;
|
||||
|
||||
r_ = (r * _matrix[0] + g * _matrix[1] + b * _matrix[2] + 255 * _matrix[3]) / 2048;
|
||||
if (r_ < 0) r_ = 0;
|
||||
if (r_ > 0xFF) r_ = 0xFF;
|
||||
|
||||
g_ = (r * _matrix[4] + g * _matrix[5] + b * _matrix[6] + 255 * _matrix[7]) / 2048;
|
||||
if (g_ < 0) g_ = 0;
|
||||
if (g_ > 0xFF) g_ = 0xFF;
|
||||
|
||||
b_ = (r * _matrix[8] + g * _matrix[9] + b * _matrix[10] + 255 * _matrix[11]) / 2048;
|
||||
if (b_ < 0) b_ = 0;
|
||||
if (b_ > 0xFF) b_ = 0xFF;
|
||||
}
|
||||
|
||||
void Palette::updateNativeMap(const Graphics::PixelFormat &format, int maxindex) {
|
||||
if (maxindex == 0)
|
||||
maxindex = size();
|
||||
|
||||
for (int i = 0; i < maxindex; i++) {
|
||||
int32 r, g, b;
|
||||
byte sr, sg, sb;
|
||||
|
||||
// Normal palette
|
||||
get(i, sr, sg, sb);
|
||||
if (format.isCLUT8()) {
|
||||
_native_untransformed[i] = i;
|
||||
} else {
|
||||
_native_untransformed[i] = format.RGBToColor(sr, sg, sb);
|
||||
}
|
||||
|
||||
r = _matrix[0] * sr +
|
||||
_matrix[1] * sg +
|
||||
_matrix[2] * sb +
|
||||
_matrix[3] * 255;
|
||||
if (r < 0)
|
||||
r = 0;
|
||||
if (r > 0x7F800)
|
||||
r = 0x7F800;
|
||||
r = r >> 11;
|
||||
|
||||
g = _matrix[4] * sr +
|
||||
_matrix[5] * sg +
|
||||
_matrix[6] * sb +
|
||||
_matrix[7] * 255;
|
||||
if (g < 0)
|
||||
g = 0;
|
||||
if (g > 0x7F800)
|
||||
g = 0x7F800;
|
||||
g = g >> 11;
|
||||
|
||||
b = _matrix[8] * sr +
|
||||
_matrix[9] * sg +
|
||||
_matrix[10] * sb +
|
||||
_matrix[11] * 255;
|
||||
if (b < 0)
|
||||
b = 0;
|
||||
if (b > 0x7F800)
|
||||
b = 0x7F800;
|
||||
b = b >> 11;
|
||||
|
||||
// Transformed normal palette
|
||||
if (format.isCLUT8()) {
|
||||
_native[i] = findBestColor(static_cast<uint8>(r),
|
||||
static_cast<uint8>(g),
|
||||
static_cast<uint8>(b));
|
||||
} else {
|
||||
_native[i] = format.RGBToColor(static_cast<uint8>(r),
|
||||
static_cast<uint8>(g),
|
||||
static_cast<uint8>(b));
|
||||
}
|
||||
|
||||
// Transformed XFORM palette (Uses the TEX32 format)
|
||||
if (TEX32_A(_xform_untransformed[i])) {
|
||||
r = _matrix[0] * TEX32_R(_xform_untransformed[i]) +
|
||||
_matrix[1] * TEX32_G(_xform_untransformed[i]) +
|
||||
_matrix[2] * TEX32_B(_xform_untransformed[i]) +
|
||||
_matrix[3] * 255;
|
||||
if (r < 0)
|
||||
r = 0;
|
||||
if (r > 0x7F800)
|
||||
r = 0x7F800;
|
||||
|
||||
g = _matrix[4] * TEX32_R(_xform_untransformed[i]) +
|
||||
_matrix[5] * TEX32_G(_xform_untransformed[i]) +
|
||||
_matrix[6] * TEX32_B(_xform_untransformed[i]) +
|
||||
_matrix[7] * 255;
|
||||
if (g < 0)
|
||||
g = 0;
|
||||
if (g > 0x7F800)
|
||||
g = 0x7F800;
|
||||
|
||||
b = _matrix[8] * TEX32_R(_xform_untransformed[i]) +
|
||||
_matrix[9] * TEX32_G(_xform_untransformed[i]) +
|
||||
_matrix[10] * TEX32_B(_xform_untransformed[i]) +
|
||||
_matrix[11] * 255;
|
||||
if (b < 0)
|
||||
b = 0;
|
||||
if (b > 0x7F800)
|
||||
b = 0x7F800;
|
||||
|
||||
_xform[i] = TEX32_PACK_RGBA(static_cast<uint8>(r >> 11),
|
||||
static_cast<uint8>(g >> 11),
|
||||
static_cast<uint8>(b >> 11),
|
||||
TEX32_A(_xform_untransformed[i]));
|
||||
} else
|
||||
_xform[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
77
engines/ultima/ultima8/gfx/palette.h
Normal file
77
engines/ultima/ultima8/gfx/palette.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_PALETTE_H
|
||||
#define ULTIMA8_GFX_PALETTE_H
|
||||
|
||||
#include "graphics/palette.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "ultima/ultima8/gfx/pal_transforms.h"
|
||||
|
||||
namespace Common {
|
||||
class ReadStream;
|
||||
}
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Palette: public Graphics::Palette {
|
||||
public:
|
||||
Palette() : Graphics::Palette(256) {}
|
||||
|
||||
void load(Common::ReadStream &rs, Common::ReadStream &xformrs);
|
||||
void load(Common::ReadStream &rs);
|
||||
|
||||
// Transform a single set of rgb values based on the current matrix.
|
||||
// Not designed for speed - just useful for one-offs.
|
||||
void transformRGB(int &r, int &g, int &b) const;
|
||||
|
||||
// Update the palette maps based on the pixel format and the current transformation matrix
|
||||
void updateNativeMap(const Graphics::PixelFormat &format, int maxindex = 0);
|
||||
|
||||
// Untransformed pixel format palette map
|
||||
uint32 _native_untransformed[256];
|
||||
|
||||
// Transformed pixel format palette map
|
||||
uint32 _native[256];
|
||||
|
||||
// Untransformed XFORM ARGB palette map
|
||||
uint32 _xform_untransformed[256];
|
||||
|
||||
// Transformed XFORM ARGB palette map
|
||||
uint32 _xform[256];
|
||||
|
||||
// Colour transformation matrix (for fades, hue shifts)
|
||||
// Applied by the RenderSurface (fixed -4.11)
|
||||
// R = R*matrix[0] + G*matrix[1] + B*matrix[2] + matrix[3];
|
||||
// G = R*matrix[4] + G*matrix[5] + B*matrix[6] + matrix[7];
|
||||
// B = R*matrix[8] + G*matrix[9] + B*matrix[10] + matrix[11];
|
||||
// A = A;
|
||||
int16 _matrix[12];
|
||||
|
||||
// The current palette transform
|
||||
PalTransforms _transform;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
360
engines/ultima/ultima8/gfx/palette_fader_process.cpp
Normal file
360
engines/ultima/ultima8/gfx/palette_fader_process.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
/* 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 "ultima/ultima8/gfx/palette_fader_process.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/kernel/kernel.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
PaletteFaderProcess *PaletteFaderProcess::_fader = nullptr;
|
||||
|
||||
// p_dynamic_class stuff
|
||||
DEFINE_RUNTIME_CLASSTYPE_CODE(PaletteFaderProcess)
|
||||
|
||||
PaletteFaderProcess::PaletteFaderProcess() : Process(), _priority(0),
|
||||
_counter(0), _maxCounter(0) {
|
||||
}
|
||||
|
||||
PaletteFaderProcess::PaletteFaderProcess(PalTransforms trans,
|
||||
int priority, int frames) : _priority(priority),
|
||||
_counter(frames), _maxCounter(frames) {
|
||||
PaletteManager *pm = PaletteManager::get_instance();
|
||||
Palette *pal = pm->getPalette(PaletteManager::Pal_Game);
|
||||
for (int i = 0; i < 12; i++) _oldMatrix[i] = pal->_matrix[i];
|
||||
pm->getTransformMatrix(_newMatrix, trans);
|
||||
pal->_transform = trans;
|
||||
}
|
||||
|
||||
PaletteFaderProcess::PaletteFaderProcess(uint32 col32, bool from,
|
||||
int priority, int frames, bool current) : _priority(priority),
|
||||
_counter(frames), _maxCounter(frames) {
|
||||
PaletteManager *pm = PaletteManager::get_instance();
|
||||
Palette *pal = pm->getPalette(PaletteManager::Pal_Game);
|
||||
if (!from) {
|
||||
if (current)
|
||||
for (int i = 0; i < 12; i++) _oldMatrix[i] = pal->_matrix[i];
|
||||
else
|
||||
pm->getTransformMatrix(_oldMatrix, pal->_transform);
|
||||
pm->getTransformMatrix(_newMatrix, col32);
|
||||
} else {
|
||||
pm->getTransformMatrix(_oldMatrix, col32);
|
||||
if (current)
|
||||
for (int i = 0; i < 12; i++) _newMatrix[i] = pal->_matrix[i];
|
||||
else
|
||||
pm->getTransformMatrix(_newMatrix, pal->_transform);
|
||||
}
|
||||
}
|
||||
|
||||
PaletteFaderProcess::PaletteFaderProcess(const int16 from[12], const int16 to[12],
|
||||
int priority, int frames) : _priority(priority),
|
||||
_counter(frames), _maxCounter(frames) {
|
||||
int i;
|
||||
for (i = 0; i < 12; i++) _oldMatrix[i] = from[i];
|
||||
for (i = 0; i < 12; i++) _newMatrix[i] = to[i];
|
||||
}
|
||||
|
||||
PaletteFaderProcess::~PaletteFaderProcess(void) {
|
||||
if (_fader == this)
|
||||
_fader = nullptr;
|
||||
}
|
||||
|
||||
void PaletteFaderProcess::run() {
|
||||
int16 matrix[12];
|
||||
|
||||
for (int i = 0; i < 12; i++) {
|
||||
int32 o = _oldMatrix[i] * _counter;
|
||||
int32 n = _newMatrix[i] * (_maxCounter - _counter);
|
||||
matrix[i] = static_cast<int16>((o + n) / _maxCounter);
|
||||
}
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(
|
||||
PaletteManager::Pal_Game,
|
||||
matrix);
|
||||
|
||||
if (!_counter--) terminate();
|
||||
}
|
||||
|
||||
void PaletteFaderProcess::saveData(Common::WriteStream *ws) {
|
||||
Process::saveData(ws);
|
||||
|
||||
ws->writeUint32LE(static_cast<uint32>(_priority));
|
||||
ws->writeUint32LE(static_cast<uint32>(_counter));
|
||||
ws->writeUint32LE(static_cast<uint32>(_maxCounter));
|
||||
unsigned int i;
|
||||
for (i = 0; i < 12; ++i)
|
||||
ws->writeUint16LE(_oldMatrix[i]);
|
||||
for (i = 0; i < 12; ++i)
|
||||
ws->writeUint16LE(_newMatrix[i]);
|
||||
}
|
||||
|
||||
bool PaletteFaderProcess::loadData(Common::ReadStream *rs, uint32 version) {
|
||||
if (!Process::loadData(rs, version)) return false;
|
||||
|
||||
_priority = static_cast<int>(rs->readUint32LE());
|
||||
_counter = static_cast<int>(rs->readUint32LE());
|
||||
_maxCounter = static_cast<int>(rs->readUint32LE());
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < 12; ++i)
|
||||
_oldMatrix[i] = rs->readUint16LE();
|
||||
for (i = 0; i < 12; ++i)
|
||||
_newMatrix[i] = rs->readUint16LE();
|
||||
|
||||
_fader = this; //static
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToPaletteTransform(const uint8 *args,
|
||||
unsigned int /*argsize*/) {
|
||||
ARG_UINT16(transform);
|
||||
ARG_UINT16(priority);
|
||||
|
||||
// If current _fader has higher _priority, we do nothing
|
||||
if (_fader && _fader->_priority > priority)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
_fader = new PaletteFaderProcess(static_cast<PalTransforms>(transform),
|
||||
priority, 45);
|
||||
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToBlack(const uint8 *args,
|
||||
unsigned int argsize) {
|
||||
if (_fader && _fader->_priority > 0x7FFF)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
int nsteps = (GAME_IS_U8 ? 30 : 40);
|
||||
if (argsize > 0) {
|
||||
ARG_UINT16(n);
|
||||
nsteps = n;
|
||||
if (argsize > 2) {
|
||||
ARG_UINT16(unk);
|
||||
warning("PaletteFaderProcess::I_fadeToBlackWithParam: Ignoring param %d", unk);
|
||||
}
|
||||
}
|
||||
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0x00, 0x00, 0x00, 0x00), false, 0x7FFF, nsteps, true);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeFromBlack(const uint8 *args,
|
||||
unsigned int argsize) {
|
||||
if (_fader && _fader->_priority > 0x7FFF)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
int nsteps = (GAME_IS_U8 ? 30 : 40);
|
||||
if (argsize > 0) {
|
||||
ARG_UINT16(n);
|
||||
nsteps = n;
|
||||
if (argsize > 2) {
|
||||
ARG_UINT16(unk);
|
||||
warning("PaletteFaderProcess::I_fadeFromBlackWithParam: Ignoring param %d", unk);
|
||||
}
|
||||
}
|
||||
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0x00, 0x00, 0x00, 0x00), true, 0x7FFF, nsteps, false);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToWhite(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0xFF, 0xFF, 0xFF, 0x00), false, 0x7FFF, 30, true);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeFromWhite(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0xFF, 0xFF, 0xFF, 0x00), true, 0x7FFF, 30, false);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_lightningBolt(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > -1)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
_fader = new PaletteFaderProcess(TEX32_PACK_RGBA(0xCF, 0xCF, 0xCF, 0x3F), true, -1, 10, false);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
static const int16 NoFadeMatrix[] = {0x800, 0, 0, 0,
|
||||
0, 0x800, 0, 0,
|
||||
0, 0, 0x800, 0
|
||||
};
|
||||
// Transform used in Crusader is Yib. We only care about Y:
|
||||
// Y = (r * 0.299 + g * 0.587 + b * 0.114)
|
||||
static const int16 GreyFadeMatrix[] = {612, 1202, 233, 0,
|
||||
612, 1202, 233, 0,
|
||||
612, 1202, 233, 0
|
||||
};
|
||||
|
||||
static const int16 AllWhiteMatrix[] = {0, 0, 0, 0x7ff,
|
||||
0, 0, 0, 0x7ff,
|
||||
0, 0, 0, 0x7ff
|
||||
};
|
||||
|
||||
static const int16 AllBlackMatrix[] = {0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToGreyScale(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
_fader = new PaletteFaderProcess(NoFadeMatrix, GreyFadeMatrix, 0x7FFF, 1);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToGivenColor(const uint8 *args,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
// TODO: guessing that color order should be same as other one below?
|
||||
ARG_UINT8(r);
|
||||
ARG_UINT8(g);
|
||||
ARG_UINT8(b);
|
||||
ARG_UINT16(nsteps);
|
||||
ARG_UINT16(unk);
|
||||
|
||||
uint32 target = (r << 16) | (g << 8) | (b << 0);
|
||||
|
||||
warning("PaletteFaderProcess::I_fadeToGivenColor: Ignoring param %d", unk);
|
||||
|
||||
_fader = new PaletteFaderProcess(target, true, 0x7FFF, nsteps, false);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_fadeToGamePal(const uint8 *args,
|
||||
unsigned int argsize) {
|
||||
if (_fader && _fader->_priority > 0x7FFF)
|
||||
return 0;
|
||||
else if (_fader && !_fader->is_terminated())
|
||||
_fader->terminate();
|
||||
|
||||
int nsteps = (GAME_IS_U8 ? 30 : 20);
|
||||
if (argsize > 0) {
|
||||
ARG_UINT16(n);
|
||||
nsteps = n;
|
||||
if (argsize > 2) {
|
||||
ARG_UINT16(unk);
|
||||
warning("PaletteFaderProcess::I_fadeToGamePalWithParam: Ignoring param %d", unk);
|
||||
}
|
||||
}
|
||||
|
||||
int16 curmatrix[12];
|
||||
PaletteManager *pm = PaletteManager::get_instance();
|
||||
pm->getTransformMatrix(curmatrix, PaletteManager::Pal_Game);
|
||||
_fader = new PaletteFaderProcess(curmatrix, NoFadeMatrix, 0x7FFF, nsteps);
|
||||
return Kernel::get_instance()->addProcess(_fader);
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_jumpToGreyScale(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
|
||||
GreyFadeMatrix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_jumpToAllBlack(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
|
||||
AllBlackMatrix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_jumpToAllWhite(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
|
||||
AllWhiteMatrix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_jumpToAllGivenColor(const uint8 *args,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
ARG_UINT8(r);
|
||||
ARG_UINT8(g);
|
||||
ARG_UINT8(b);
|
||||
|
||||
// Transform matrix goes 0~2048, scale 0-63 vals from input
|
||||
const int16 r16 = static_cast<int16>(r) * 32;
|
||||
const int16 g16 = static_cast<int16>(g) * 32;
|
||||
const int16 b16 = static_cast<int16>(b) * 32;
|
||||
|
||||
const int16 color_matrix[] = {0, 0, 0, r16,
|
||||
0, 0, 0, g16,
|
||||
0, 0, 0, b16
|
||||
};
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
|
||||
color_matrix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 PaletteFaderProcess::I_jumpToNormalPalette(const uint8 * /*args*/,
|
||||
unsigned int /*argsize*/) {
|
||||
if (_fader && _fader->_priority > 0x7FFF) return 0;
|
||||
else if (_fader) _fader->terminate();
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game,
|
||||
NoFadeMatrix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
75
engines/ultima/ultima8/gfx/palette_fader_process.h
Normal file
75
engines/ultima/ultima8/gfx/palette_fader_process.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_PALETTEFADERPROCESS_H
|
||||
#define ULTIMA8_GFX_PALETTEFADERPROCESS_H
|
||||
|
||||
#include "ultima/ultima8/kernel/process.h"
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/usecode/intrinsics.h"
|
||||
#include "ultima/ultima8/misc/classtype.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/** A process to fade the palette from one transform matrix to another */
|
||||
class PaletteFaderProcess : public Process {
|
||||
int _priority;
|
||||
int32 _counter;
|
||||
int32 _maxCounter;
|
||||
int16 _oldMatrix[12]; // Fixed point -4.11
|
||||
int16 _newMatrix[12];
|
||||
public:
|
||||
static PaletteFaderProcess *_fader;
|
||||
|
||||
// p_dynamic_class stuff
|
||||
ENABLE_RUNTIME_CLASSTYPE()
|
||||
PaletteFaderProcess();
|
||||
PaletteFaderProcess(PalTransforms trans, int priority, int frames);
|
||||
PaletteFaderProcess(uint32 rgba, bool from, int priority, int frames, bool current);
|
||||
PaletteFaderProcess(const int16 from[12], const int16 to[12], int priority, int frames);
|
||||
~PaletteFaderProcess(void) override;
|
||||
|
||||
void run() override;
|
||||
|
||||
INTRINSIC(I_fadeToPaletteTransform);
|
||||
INTRINSIC(I_fadeToBlack);
|
||||
INTRINSIC(I_fadeFromWhite);
|
||||
INTRINSIC(I_fadeToWhite);
|
||||
INTRINSIC(I_fadeFromBlack);
|
||||
INTRINSIC(I_lightningBolt);
|
||||
INTRINSIC(I_fadeToGreyScale);
|
||||
INTRINSIC(I_fadeToGivenColor);
|
||||
INTRINSIC(I_fadeToGamePal);
|
||||
INTRINSIC(I_jumpToGreyScale);
|
||||
INTRINSIC(I_jumpToAllBlack);
|
||||
INTRINSIC(I_jumpToAllWhite);
|
||||
INTRINSIC(I_jumpToAllGivenColor);
|
||||
INTRINSIC(I_jumpToNormalPalette);
|
||||
|
||||
bool loadData(Common::ReadStream *rs, uint32 version);
|
||||
void saveData(Common::WriteStream *ws) override;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
358
engines/ultima/ultima8/gfx/palette_manager.cpp
Normal file
358
engines/ultima/ultima8/gfx/palette_manager.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/palette_manager.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
PaletteManager *PaletteManager::_paletteManager = nullptr;
|
||||
|
||||
PaletteManager::PaletteManager(const Graphics::PixelFormat &format) : _format(format) {
|
||||
debug(1, "Creating PaletteManager...");
|
||||
|
||||
_paletteManager = this;
|
||||
}
|
||||
|
||||
PaletteManager::~PaletteManager() {
|
||||
reset();
|
||||
debug(1, "Destroying PaletteManager...");
|
||||
_paletteManager = nullptr;
|
||||
}
|
||||
|
||||
// Reset the Palette Manager
|
||||
void PaletteManager::reset() {
|
||||
debug(1, "Resetting PaletteManager...");
|
||||
|
||||
for (unsigned int i = 0; i < _palettes.size(); ++i)
|
||||
delete _palettes[i];
|
||||
_palettes.clear();
|
||||
}
|
||||
|
||||
void PaletteManager::updatedPalette(PalIndex index, int maxindex) {
|
||||
Palette *pal = getPalette(index);
|
||||
if (pal)
|
||||
pal->updateNativeMap(_format, maxindex);
|
||||
}
|
||||
|
||||
// Reset all the transforms back to default
|
||||
void PaletteManager::resetTransforms() {
|
||||
debug(1, "Resetting Palette Transforms...");
|
||||
|
||||
int16 matrix[12];
|
||||
getTransformMatrix(matrix, Transform_None);
|
||||
|
||||
for (unsigned int i = 0; i < _palettes.size(); ++i) {
|
||||
Palette *pal = _palettes[i];
|
||||
if (!pal) continue;
|
||||
pal->_transform = Transform_None;
|
||||
for (int j = 0; j < 12; j++)
|
||||
pal->_matrix[j] = matrix[j];
|
||||
pal->updateNativeMap(_format);
|
||||
}
|
||||
}
|
||||
|
||||
bool PaletteManager::loadTransforms(Common::ReadStream& rs) {
|
||||
int16 matrix[12];
|
||||
for (int i = 0; i < 12; i++)
|
||||
matrix[i] = rs.readUint16LE();
|
||||
|
||||
PaletteManager::get_instance()->transformPalette(PaletteManager::Pal_Game, matrix);
|
||||
Palette *pal = getPalette(PaletteManager::Pal_Game);
|
||||
pal->_transform = static_cast<PalTransforms>(rs.readUint16LE());
|
||||
|
||||
if (pal->_transform >= Transform_Invalid) {
|
||||
warning("Invalid palette transform %d. Corrupt savegame?", static_cast<int>(pal->_transform));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaletteManager::saveTransforms(Common::WriteStream& ws) {
|
||||
Palette *pal = getPalette(PaletteManager::Pal_Game);
|
||||
for (int i = 0; i < 12; i++)
|
||||
ws.writeUint16LE(pal->_matrix[i]);
|
||||
ws.writeUint16LE(pal->_transform);
|
||||
}
|
||||
|
||||
void PaletteManager::PixelFormatChanged(const Graphics::PixelFormat &format) {
|
||||
_format = format;
|
||||
|
||||
// Create native _palettes for all currently loaded _palettes
|
||||
for (unsigned int i = 0; i < _palettes.size(); ++i)
|
||||
if (_palettes[i])
|
||||
_palettes[i]->updateNativeMap(_format);
|
||||
}
|
||||
|
||||
void PaletteManager::load(PalIndex index, Common::ReadStream &rs, Common::ReadStream &xformrs) {
|
||||
if (_palettes.size() <= static_cast<unsigned int>(index))
|
||||
_palettes.resize(index + 1);
|
||||
|
||||
if (_palettes[index])
|
||||
delete _palettes[index];
|
||||
|
||||
Palette *pal = new Palette;
|
||||
pal->load(rs, xformrs);
|
||||
pal->updateNativeMap(_format);
|
||||
|
||||
_palettes[index] = pal;
|
||||
}
|
||||
|
||||
void PaletteManager::load(PalIndex index, Common::ReadStream &rs) {
|
||||
if (_palettes.size() <= static_cast<unsigned int>(index))
|
||||
_palettes.resize(index + 1);
|
||||
|
||||
if (_palettes[index])
|
||||
delete _palettes[index];
|
||||
|
||||
Palette *pal = new Palette;
|
||||
pal->load(rs);
|
||||
pal->updateNativeMap(_format);
|
||||
|
||||
_palettes[index] = pal;
|
||||
}
|
||||
|
||||
void PaletteManager::duplicate(PalIndex src, PalIndex dest) {
|
||||
Palette *newpal = getPalette(dest);
|
||||
if (!newpal)
|
||||
newpal = new Palette;
|
||||
Palette *srcpal = getPalette(src);
|
||||
if (srcpal)
|
||||
*newpal = *srcpal;
|
||||
|
||||
newpal->updateNativeMap(_format);
|
||||
if (_palettes.size() <= static_cast<unsigned int>(dest))
|
||||
_palettes.resize(dest + 1);
|
||||
_palettes[dest] = newpal;
|
||||
}
|
||||
|
||||
Palette *PaletteManager::getPalette(PalIndex index) {
|
||||
if (static_cast<unsigned int>(index) >= _palettes.size())
|
||||
return nullptr;
|
||||
|
||||
return _palettes[index];
|
||||
}
|
||||
|
||||
void PaletteManager::transformPalette(PalIndex index, const int16 matrix[12]) {
|
||||
Palette *pal = getPalette(index);
|
||||
if (pal) {
|
||||
for (int i = 0; i < 12; i++)
|
||||
pal->_matrix[i] = matrix[i];
|
||||
pal->updateNativeMap(_format);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteManager::untransformPalette(PalIndex index) {
|
||||
Palette *pal = getPalette(index);
|
||||
|
||||
if (!pal) return;
|
||||
|
||||
pal->_transform = Transform_None;
|
||||
int16 matrix[12];
|
||||
getTransformMatrix(matrix, Transform_None);
|
||||
transformPalette(index, matrix);
|
||||
}
|
||||
|
||||
bool PaletteManager::getTransformMatrix(int16 matrix[12], PalIndex index) {
|
||||
Palette *pal = getPalette(index);
|
||||
|
||||
if (!pal) return false;
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
matrix[i] = pal->_matrix[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaletteManager::getTransformMatrix(int16 matrix[12], PalTransforms trans) {
|
||||
switch (trans) {
|
||||
// Normal untransformed palette
|
||||
case Transform_None: {
|
||||
matrix[0] = 0x800;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = 0;
|
||||
matrix[3] = 0;
|
||||
matrix[4] = 0;
|
||||
matrix[5] = 0x800;
|
||||
matrix[6] = 0;
|
||||
matrix[7] = 0;
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = 0x800;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// O[i] = I[r]*0.375 + I[g]*0.5 + I[b]*0.125;
|
||||
case Transform_Greyscale: {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
matrix[i * 4 + 0] = 0x0300;
|
||||
matrix[i * 4 + 1] = 0x0400;
|
||||
matrix[i * 4 + 2] = 0x0100;
|
||||
matrix[i * 4 + 3] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// O[r] = 0;
|
||||
case Transform_NoRed: {
|
||||
matrix[0] = 0;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = 0;
|
||||
matrix[3] = 0;
|
||||
matrix[4] = 0;
|
||||
matrix[5] = 0x800;
|
||||
matrix[6] = 0;
|
||||
matrix[7] = 0;
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = 0x800;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// O[i] = (I[i] + Grey)*0.25 + 0.1875;
|
||||
case Transform_RainStorm: {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
matrix[i * 4 + 0] = (0x0300 * 0x0200) >> 11;
|
||||
matrix[i * 4 + 1] = (0x0400 * 0x0200) >> 11;
|
||||
matrix[i * 4 + 2] = (0x0100 * 0x0200) >> 11;
|
||||
|
||||
matrix[i * 4 + i] += 0x0200;
|
||||
|
||||
matrix[i * 4 + 3] = 0x0180;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// O[r] = I[r]*0.5 + Grey*0.5 + 0.1875;
|
||||
// O[g] = I[g]*0.5 + Grey*0.25;
|
||||
// O[b] = I[b]*0.5;
|
||||
case Transform_FireStorm: {
|
||||
// O[r] = I[r]*0.5 + Grey*0.5 + 0.1875;
|
||||
matrix[0] = ((0x0300 * 0x0400) >> 11) + 0x0400;
|
||||
matrix[1] = (0x0400 * 0x0400) >> 11;
|
||||
matrix[2] = (0x0100 * 0x0400) >> 11;
|
||||
matrix[3] = 0x0180;
|
||||
|
||||
// O[g] = I[g]*0.5 + Grey*0.25;
|
||||
matrix[4] = (0x0300 * 0x0200) >> 11;
|
||||
matrix[5] = ((0x0400 * 0x0200) >> 11) + 0x0400;
|
||||
matrix[6] = (0x0100 * 0x0200) >> 11;
|
||||
matrix[7] = 0;
|
||||
|
||||
// O[b] = I[b]*0.5;
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = 0x0400;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// O[i] = I[i]*2 -Grey;
|
||||
case Transform_Saturate: {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
matrix[i * 4 + 0] = -0x0300;
|
||||
matrix[i * 4 + 1] = -0x0400;
|
||||
matrix[i * 4 + 2] = -0x0100;
|
||||
matrix[i * 4 + 3] = 0;
|
||||
matrix[i * 4 + i] += 0x1000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// O[b] = I[r]; O[r] = I[g]; O[g] = I[b];
|
||||
case Transform_BRG: {
|
||||
matrix[0] = 0;
|
||||
matrix[1] = 0x800;
|
||||
matrix[2] = 0;
|
||||
matrix[3] = 0;
|
||||
matrix[4] = 0;
|
||||
matrix[5] = 0;
|
||||
matrix[6] = 0x800;
|
||||
matrix[7] = 0;
|
||||
matrix[8] = 0x800;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = 0;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// O[g] = I[r]; O[b] = I[g]; O[r] = I[b];
|
||||
case Transform_GBR: {
|
||||
matrix[0] = 0;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = 0x800;
|
||||
matrix[3] = 0;
|
||||
matrix[4] = 0x800;
|
||||
matrix[5] = 0;
|
||||
matrix[6] = 0;
|
||||
matrix[7] = 0;
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0x800;
|
||||
matrix[10] = 0;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
// Unknown
|
||||
default: {
|
||||
warning("Unknown Palette Transformation: %d", trans);
|
||||
matrix[0] = 0x800;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = 0;
|
||||
matrix[3] = 0;
|
||||
matrix[4] = 0;
|
||||
matrix[5] = 0x800;
|
||||
matrix[6] = 0;
|
||||
matrix[7] = 0;
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = 0x800;
|
||||
matrix[11] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PaletteManager::getTransformMatrix(int16 matrix[12], uint32 col32) {
|
||||
matrix[0] = (static_cast<int32>(TEX32_A(col32)) * 0x800) / 255;
|
||||
matrix[1] = 0;
|
||||
matrix[2] = 0;
|
||||
matrix[3] = (static_cast<int32>(TEX32_R(col32)) * 0x800) / 255;
|
||||
|
||||
matrix[4] = 0;
|
||||
matrix[5] = (static_cast<int32>(TEX32_A(col32)) * 0x800) / 255;
|
||||
matrix[6] = 0;
|
||||
matrix[7] = (static_cast<int32>(TEX32_G(col32)) * 0x800) / 255;
|
||||
|
||||
matrix[8] = 0;
|
||||
matrix[9] = 0;
|
||||
matrix[10] = (static_cast<int32>(TEX32_A(col32)) * 0x800) / 255;
|
||||
matrix[11] = (static_cast<int32>(TEX32_B(col32)) * 0x800) / 255;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
103
engines/ultima/ultima8/gfx/palette_manager.h
Normal file
103
engines/ultima/ultima8/gfx/palette_manager.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_PALETTEMANAGER_H
|
||||
#define ULTIMA8_GFX_PALETTEMANAGER_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "ultima/ultima8/gfx/pal_transforms.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Palette;
|
||||
|
||||
class PaletteManager {
|
||||
public:
|
||||
explicit PaletteManager(const Graphics::PixelFormat &format);
|
||||
~PaletteManager();
|
||||
|
||||
static PaletteManager *get_instance() {
|
||||
return _paletteManager;
|
||||
}
|
||||
|
||||
enum PalIndex {
|
||||
Pal_Game = 0,
|
||||
Pal_Movie = 1,
|
||||
Pal_Diff = 2, // Crusaders only - difficulty screen??
|
||||
Pal_Misc = 3, // Crusaders only - game menu
|
||||
Pal_Misc2 = 4, // Crusaders only - ??
|
||||
Pal_Star = 5, // Crusaders only - ??
|
||||
Pal_Cred = 6, // Crusader: No regret only (but mentioned in the no remorse exe!)
|
||||
Pal_JPFontStart = 16
|
||||
};
|
||||
|
||||
void load(PalIndex index, Common::ReadStream &rs, Common::ReadStream &xformrs);
|
||||
void load(PalIndex index, Common::ReadStream &rs);
|
||||
Palette *getPalette(PalIndex index);
|
||||
uint getNumPalettes() const { return _palettes.size(); }
|
||||
|
||||
void duplicate(PalIndex src, PalIndex dest);
|
||||
|
||||
//! Re-convert a palette to native format after modifying it. If maxindex is set,
|
||||
//! only recalculate color indexes up to that value.
|
||||
void updatedPalette(PalIndex index, int maxindex = 0);
|
||||
|
||||
//! Apply a transform matrix to a palette (-4.11 fixed)
|
||||
void transformPalette(PalIndex index, const int16 matrix[12]);
|
||||
|
||||
//! reset the transformation matrix of a palette
|
||||
void untransformPalette(PalIndex index);
|
||||
|
||||
//! Get the current TransformMatrix for the given index
|
||||
bool getTransformMatrix(int16 matrix[12], PalIndex index);
|
||||
|
||||
// Get a TransformMatrix from a PalTransforms value (-4.11 fixed)
|
||||
static void getTransformMatrix(int16 matrix[12],
|
||||
PalTransforms trans);
|
||||
|
||||
// Create a custom Transform Matrix from RGBA col32. (-4.11 fixed)
|
||||
// Alpha will set how much of original palette to keep. 0 = keep none
|
||||
static void getTransformMatrix(int16 matrix[12], uint32 col32);
|
||||
|
||||
//! Change the pixel format used by the PaletteManager
|
||||
void PixelFormatChanged(const Graphics::PixelFormat &format);
|
||||
|
||||
//! Reset the Palette Manager
|
||||
void reset();
|
||||
|
||||
//! Reset all the transforms back to default
|
||||
void resetTransforms();
|
||||
bool loadTransforms(Common::ReadStream &rs);
|
||||
void saveTransforms(Common::WriteStream &ws);
|
||||
|
||||
private:
|
||||
Std::vector<Palette *> _palettes;
|
||||
Graphics::PixelFormat _format;
|
||||
|
||||
static PaletteManager *_paletteManager;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
174
engines/ultima/ultima8/gfx/raw_shape_frame.cpp
Normal file
174
engines/ultima/ultima8/gfx/raw_shape_frame.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/raw_shape_frame.h"
|
||||
#include "ultima/ultima8/convert/u8/convert_shape_u8.h"
|
||||
#include "ultima/ultima8/misc/stream_util.h"
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
/*
|
||||
parse data and fill class
|
||||
*/
|
||||
RawShapeFrame::RawShapeFrame(const uint8 *data, uint32 size, const ConvertShapeFormat *format,
|
||||
const uint8 special[256], ConvertShapeFrame *prev) : _line_offsets(0),
|
||||
_rle_data(nullptr) {
|
||||
// Load it as u8
|
||||
if (!format || format == &U8ShapeFormat || format == &U82DShapeFormat)
|
||||
loadU8Format(data, size);
|
||||
else if (format == &PentagramShapeFormat)
|
||||
loadPentagramFormat(data, size);
|
||||
else if (format == &U8CMPShapeFormat)
|
||||
loadU8CMPFormat(data, size, format, special, prev);
|
||||
else
|
||||
loadGenericFormat(data, size, format);
|
||||
}
|
||||
|
||||
RawShapeFrame::~RawShapeFrame() {
|
||||
delete [] _line_offsets;
|
||||
}
|
||||
|
||||
// This will load a u8 style shape 'optimized'.
|
||||
void RawShapeFrame::loadU8Format(const uint8 *data, uint32 size) {
|
||||
Common::MemoryReadStream stream(data, size + 8);
|
||||
|
||||
stream.skip(8); // skip header
|
||||
_compressed = stream.readByte();
|
||||
stream.skip(1);
|
||||
_width = stream.readSint16LE();
|
||||
_height = stream.readSint16LE();
|
||||
_xoff = stream.readSint16LE();
|
||||
_yoff = stream.readSint16LE();
|
||||
|
||||
if (_height == 0)
|
||||
return;
|
||||
|
||||
_line_offsets = new uint32[_height];
|
||||
|
||||
for (int32 i = 0; i < _height; i++) {
|
||||
_line_offsets[i] = stream.readUint16LE() - ((_height - i) * 2);
|
||||
}
|
||||
|
||||
_rle_data = data + stream.pos();
|
||||
}
|
||||
|
||||
// This will load a pentagram style shape 'optimized'.
|
||||
void RawShapeFrame::loadPentagramFormat(const uint8 *data, uint32 size) {
|
||||
Common::MemoryReadStream stream(data, size);
|
||||
|
||||
_compressed = stream.readByte();
|
||||
stream.skip(3);
|
||||
_width = stream.readSint32LE();
|
||||
_height = stream.readSint32LE();
|
||||
_xoff = stream.readSint32LE();
|
||||
_yoff = stream.readSint32LE();
|
||||
|
||||
if (_height == 0)
|
||||
return;
|
||||
|
||||
_line_offsets = new uint32[_height];
|
||||
|
||||
for (int32 i = 0; i < _height; i++) {
|
||||
_line_offsets[i] = stream.readSint32LE();
|
||||
}
|
||||
|
||||
_rle_data = data + stream.pos();
|
||||
}
|
||||
|
||||
// This will load any sort of shape via a ConvertShapeFormat struct
|
||||
void RawShapeFrame::loadGenericFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format) {
|
||||
Common::MemoryReadStream ds(data + format->_bytes_frame_unknown, size);
|
||||
|
||||
_compressed = readX(ds, format->_bytes_frame_compression);
|
||||
_width = readXS(ds, format->_bytes_frame_width);
|
||||
_height = readXS(ds, format->_bytes_frame_height);
|
||||
_xoff = readXS(ds, format->_bytes_frame_xoff);
|
||||
_yoff = readXS(ds, format->_bytes_frame_yoff);
|
||||
|
||||
if (_height == 0)
|
||||
return;
|
||||
|
||||
// Fairly arbitrary sanity check
|
||||
if (_height < 0 || _height > 4096 || _width < 0 || _width > 4096 || _xoff > 4096 || _yoff > 4096) {
|
||||
warning("got some invalid data loading shape");
|
||||
_width = _height = _xoff = _yoff = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_line_offsets = new uint32[_height];
|
||||
|
||||
for (int32 i = 0; i < _height; i++) {
|
||||
if (format->_line_offset_absolute) {
|
||||
_line_offsets[i] = readX(ds, format->_bytes_line_offset);
|
||||
} else {
|
||||
if (ds.size() - ds.pos() < (int32)format->_bytes_line_offset) {
|
||||
warning("going off end of %d buffer at %d reading %d",
|
||||
(int)ds.size(), (int)ds.pos(), format->_bytes_line_offset);
|
||||
}
|
||||
_line_offsets[i] = readX(ds, format->_bytes_line_offset) - ((_height - i) * format->_bytes_line_offset);
|
||||
}
|
||||
}
|
||||
|
||||
_rle_data = data + format->_len_frameheader2 + _height * format->_bytes_line_offset;
|
||||
}
|
||||
|
||||
// This will load an U8-compressed shape
|
||||
void RawShapeFrame::loadU8CMPFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format, const uint8 special[256], ConvertShapeFrame *prev) {
|
||||
Common::MemoryReadStream ds(data, size);
|
||||
|
||||
ConvertShapeFrame f;
|
||||
|
||||
f.ReadCmpFrame(ds, format, special, prev);
|
||||
|
||||
uint32 to_alloc = f._height + (f._bytes_rle + 3) / 4;
|
||||
_line_offsets = new uint32[to_alloc];
|
||||
_rle_data = reinterpret_cast<uint8 *>(_line_offsets + f._height);
|
||||
|
||||
_compressed = f._compression;
|
||||
_height = f._height;
|
||||
_width = f._width;
|
||||
_xoff = f._xoff;
|
||||
_yoff = f._yoff;
|
||||
|
||||
memcpy(_line_offsets, f._line_offsets, f._height * 4);
|
||||
memcpy(const_cast<uint8 *>(_rle_data), f._rle_data, f._bytes_rle);
|
||||
|
||||
f.Free();
|
||||
}
|
||||
|
||||
void RawShapeFrame::getConvertShapeFrame(ConvertShapeFrame &csf) {
|
||||
csf._compression = _compressed;
|
||||
csf._width = _width;
|
||||
csf._height = _height;
|
||||
csf._xoff = _xoff;
|
||||
csf._yoff = _yoff;
|
||||
csf._line_offsets = _line_offsets;
|
||||
csf._bytes_rle = 0;
|
||||
csf._rle_data = const_cast<uint8 *>(_rle_data);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
78
engines/ultima/ultima8/gfx/raw_shape_frame.h
Normal file
78
engines/ultima/ultima8/gfx/raw_shape_frame.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_RAW_SHAPEFRAME_H
|
||||
#define ULTIMA8_GFX_RAW_SHAPEFRAME_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
struct ConvertShapeFormat;
|
||||
struct ConvertShapeFrame;
|
||||
|
||||
/**
|
||||
* A raw shape frame just contains references into the (possibly compressed)
|
||||
* data for the shape and is used as an intermediate step in the loading
|
||||
* process.
|
||||
*/
|
||||
class RawShapeFrame {
|
||||
friend class ShapeFrame;
|
||||
public:
|
||||
|
||||
// parse data.
|
||||
//
|
||||
// You will find this is quite similar to the ConvertShapeFrame except
|
||||
// all the unknown crap is removed. It's designed to allow for painting
|
||||
// only, and for speed when loading.
|
||||
|
||||
RawShapeFrame(const uint8 *data, uint32 size, const ConvertShapeFormat *format = 0,
|
||||
const uint8 special[256] = 0, ConvertShapeFrame *prev = 0);
|
||||
~RawShapeFrame();
|
||||
|
||||
void getConvertShapeFrame(ConvertShapeFrame &csf);
|
||||
|
||||
private:
|
||||
|
||||
uint32 _compressed;
|
||||
int32 _width, _height;
|
||||
int32 _xoff, _yoff;
|
||||
|
||||
uint32 *_line_offsets; // Note these are offsets into rle_data
|
||||
const uint8 *_rle_data;
|
||||
|
||||
// This will load a u8 style shape 'optimized'.
|
||||
void loadU8Format(const uint8 *data, uint32 size);
|
||||
|
||||
// This will load a pentagram style shape 'optimized'.
|
||||
void loadPentagramFormat(const uint8 *data, uint32 size);
|
||||
|
||||
// This will load any sort of shape via a ConvertShapeFormat struct
|
||||
// Crusader shapes must be loaded this way
|
||||
void loadGenericFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format);
|
||||
|
||||
// This will load a u8-compressed shape
|
||||
void loadU8CMPFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format, const uint8 special[256], ConvertShapeFrame *prev);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
993
engines/ultima/ultima8/gfx/render_surface.cpp
Normal file
993
engines/ultima/ultima8/gfx/render_surface.cpp
Normal file
@@ -0,0 +1,993 @@
|
||||
/* 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 "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "graphics/blit.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
RenderSurface::RenderSurface(int width, int height, const Graphics::PixelFormat &format) :
|
||||
_pixels(nullptr), _ox(0), _oy(0), _pitch(0),
|
||||
_flipped(false), _clipWindow(0, 0, 0, 0), _lockCount(0),
|
||||
_disposeAfterUse(DisposeAfterUse::YES) {
|
||||
|
||||
_surface = new Graphics::ManagedSurface(width, height, format);
|
||||
_clipWindow.setWidth(_surface->w);
|
||||
_clipWindow.setHeight(_surface->h);
|
||||
|
||||
SetPixelsPointer();
|
||||
}
|
||||
|
||||
RenderSurface::RenderSurface(Graphics::ManagedSurface *s, DisposeAfterUse::Flag disposeAfterUse) :
|
||||
_pixels(nullptr), _ox(0), _oy(0), _pitch(0),
|
||||
_flipped(false), _clipWindow(0, 0, 0, 0), _lockCount(0),
|
||||
_surface(s), _disposeAfterUse(disposeAfterUse) {
|
||||
|
||||
_clipWindow.setWidth(_surface->w);
|
||||
_clipWindow.setHeight(_surface->h);
|
||||
|
||||
SetPixelsPointer();
|
||||
}
|
||||
|
||||
//
|
||||
// RenderSurface::~RenderSurface()
|
||||
//
|
||||
// Desc: Destructor
|
||||
//
|
||||
RenderSurface::~RenderSurface() {
|
||||
if (_disposeAfterUse == DisposeAfterUse::YES)
|
||||
delete _surface;
|
||||
}
|
||||
|
||||
void RenderSurface::SetPixelsPointer()
|
||||
{
|
||||
_pixels = static_cast<uint8 *>(_surface->getBasePtr(_ox, _oy));
|
||||
_pitch = _surface->pitch;
|
||||
|
||||
if (_flipped) {
|
||||
_pixels = static_cast<uint8 *>(_surface->getBasePtr(_ox, _surface->h - 1 - _oy));
|
||||
_pitch = -_pitch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// RenderSurface::BeginPainting()
|
||||
//
|
||||
// Desc: Prepare the surface for drawing this frame (in effect lock it for drawing)
|
||||
// Returns: Non Zero on error
|
||||
//
|
||||
bool RenderSurface::BeginPainting() {
|
||||
if (!_lockCount) {
|
||||
_surface->markAllDirty();
|
||||
}
|
||||
|
||||
_lockCount++;
|
||||
|
||||
// Origin offset pointers
|
||||
SetPixelsPointer();
|
||||
|
||||
// No error
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// RenderSurface::EndPainting()
|
||||
//
|
||||
// Desc: Prepare the surface for drawing this frame (in effect lock it for drawing)
|
||||
// Returns: Non Zero on error
|
||||
//
|
||||
bool RenderSurface::EndPainting() {
|
||||
// Already Unlocked
|
||||
if (!_lockCount) {
|
||||
error("Error: BeginPainting()/EndPainting() Mismatch!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decrement counter
|
||||
--_lockCount;
|
||||
|
||||
if (!_lockCount) {
|
||||
// Clear pointers
|
||||
_pixels = nullptr;
|
||||
}
|
||||
|
||||
// No error
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Common::Rect32 RenderSurface::GetSurfaceDims()
|
||||
//
|
||||
// Desc: Get the Surface Dimensions (and logical origin)
|
||||
// r: Rect object to fill
|
||||
//
|
||||
Common::Rect32 RenderSurface::getSurfaceDims() const {
|
||||
Common::Rect32 r;
|
||||
r.moveTo(_ox, _oy);
|
||||
r.setWidth(_surface->w);
|
||||
r.setHeight(_surface->h);
|
||||
return r;
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::SetOrigin(int32 x, int32 y)
|
||||
//
|
||||
// Desc: Set the Phyiscal Pixel to be the logical origin
|
||||
//
|
||||
void RenderSurface::SetOrigin(int32 x, int32 y) {
|
||||
// Adjust the clipping window
|
||||
_clipWindow.translate(_ox - x, _oy - y);
|
||||
|
||||
// Set the origin
|
||||
_ox = x;
|
||||
_oy = y;
|
||||
|
||||
// The new pointers
|
||||
SetPixelsPointer();
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::GetOrigin(int32 &x, int32 &y)
|
||||
//
|
||||
// Desc: Get the Phyiscal Pixel that is the logical origin
|
||||
//
|
||||
void RenderSurface::GetOrigin(int32 &x, int32 &y) const {
|
||||
// Set the origin
|
||||
x = _ox;
|
||||
y = _oy;
|
||||
}
|
||||
|
||||
//
|
||||
// Common::Rect32 RenderSurface::getClippingRect()
|
||||
//
|
||||
// Desc: Get the Clipping Rectangle
|
||||
// r: Rect object to fill
|
||||
//
|
||||
Common::Rect32 RenderSurface::getClippingRect() const {
|
||||
return Common::Rect32(_clipWindow.left, _clipWindow.top, _clipWindow.right, _clipWindow.bottom);
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::setClippingRect(const Common::Rect32 &r)
|
||||
//
|
||||
// Desc: Set the Clipping Rectangle
|
||||
// r: Rect object that contains new Clipping Rectangle
|
||||
//
|
||||
void RenderSurface::setClippingRect(const Common::Rect32 &r) {
|
||||
// What we need to do is to clip the clipping rect to the phyiscal screen
|
||||
_clipWindow = Common::Rect(r.left, r.top, r.right, r.bottom);
|
||||
_clipWindow.clip(Common::Rect(-_ox, -_oy, -_ox + _surface->w, -_oy + _surface->h));
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::SetFlipped(bool _flipped)
|
||||
//
|
||||
// Desc: Flip the surface
|
||||
//
|
||||
void RenderSurface::SetFlipped(bool wantFlipped) {
|
||||
_flipped = wantFlipped;
|
||||
|
||||
SetPixelsPointer();
|
||||
}
|
||||
|
||||
//
|
||||
// bool RenderSurface::IsFlipped() const
|
||||
//
|
||||
// Desc: Has the render surface been _flipped?
|
||||
//
|
||||
bool RenderSurface::IsFlipped() const {
|
||||
return _flipped;
|
||||
}
|
||||
|
||||
void RenderSurface::fillRect(const Common::Rect32 &r, uint32 color) {
|
||||
Common::Rect rect(r.left, r.top, r.right, r.bottom);
|
||||
rect.clip(_clipWindow);
|
||||
rect.translate(_ox, _oy);
|
||||
_surface->fillRect(rect, color);
|
||||
}
|
||||
|
||||
void RenderSurface::frameRect(const Common::Rect32& r, uint32 color) {
|
||||
Common::Rect rect(r.left, r.top, r.right, r.bottom);
|
||||
rect.clip(_clipWindow);
|
||||
rect.translate(_ox, _oy);
|
||||
_surface->frameRect(rect, color);
|
||||
}
|
||||
|
||||
void RenderSurface::drawLine(int32 sx, int32 sy, int32 ex, int32 ey, uint32 color) {
|
||||
_surface->drawLine(sx + _ox, sy + _oy, ex + _ox, ey + _oy, color);
|
||||
}
|
||||
|
||||
void RenderSurface::fill32(uint32 rgb, const Common::Rect32 &r) {
|
||||
Common::Rect rect(r.left, r.top, r.right, r.bottom);
|
||||
rect.clip(_clipWindow);
|
||||
rect.translate(_ox, _oy);
|
||||
rgb = _surface->format.RGBToColor(TEX32_R(rgb), TEX32_G(rgb), TEX32_B(rgb));
|
||||
_surface->fillRect(rect, rgb);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename uintX>
|
||||
void inline fillBlendedLogic(uint8 *pixels, int32 pitch, uint32 rgba, const Common::Rect &rect, const Graphics::PixelFormat &format) {
|
||||
int32 w = rect.width();
|
||||
int32 h = rect.height();
|
||||
|
||||
if (!w || !h)
|
||||
return;
|
||||
|
||||
uint32 sa = TEX32_A(rgba);
|
||||
uint32 sr = TEX32_R(rgba);
|
||||
uint32 sg = TEX32_G(rgba);
|
||||
uint32 sb = TEX32_B(rgba);
|
||||
uint32 ia = 256 - TEX32_A(rgba);
|
||||
|
||||
uint8 *pixel = pixels + rect.top * pitch + rect.left * format.bytesPerPixel;
|
||||
int diff = pitch - w * format.bytesPerPixel;
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
uintX *dest = reinterpret_cast<uintX *>(pixel);
|
||||
uint8 dr, dg, db, da;
|
||||
format.colorToARGB(*dest, da, dr, dg, db);
|
||||
|
||||
if (da) {
|
||||
dr = (dr * ia + sr * sa) >> 8;
|
||||
dg = (dg * ia + sg * sa) >> 8;
|
||||
db = (db * ia + sb * sa) >> 8;
|
||||
|
||||
*dest = format.ARGBToColor(da, dr, dg, db);
|
||||
}
|
||||
pixel += format.bytesPerPixel;
|
||||
}
|
||||
|
||||
pixel += diff;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
void RenderSurface::fillBlended(uint32 rgba, const Common::Rect32 &r) {
|
||||
int alpha = TEX32_A(rgba);
|
||||
if (alpha == 0xFF) {
|
||||
fill32(rgba, r);
|
||||
return;
|
||||
} else if (!alpha) {
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Rect rect(r.left, r.top, r.right, r.bottom);
|
||||
rect.clip(_clipWindow);
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
fillBlendedLogic<uint32>(_pixels, _pitch, rgba, rect, _surface->format);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
fillBlendedLogic<uint16>(_pixels, _pitch, rgba, rect, _surface->format);
|
||||
}
|
||||
|
||||
void RenderSurface::frameRect32(uint32 rgb, const Common::Rect32 &r) {
|
||||
Common::Rect rect(r.left, r.top, r.right, r.bottom);
|
||||
rect.clip(_clipWindow);
|
||||
rect.translate(_ox, _oy);
|
||||
rgb = _surface->format.RGBToColor(TEX32_R(rgb), TEX32_G(rgb), TEX32_B(rgb));
|
||||
_surface->frameRect(rect, rgb);
|
||||
}
|
||||
|
||||
void RenderSurface::drawLine32(uint32 rgb, int32 sx, int32 sy, int32 ex, int32 ey) {
|
||||
rgb = _surface->format.RGBToColor(TEX32_R(rgb), TEX32_G(rgb), TEX32_B(rgb));
|
||||
_surface->drawLine(sx + _ox, sy + _oy, ex + _ox, ey + _oy, rgb);
|
||||
}
|
||||
|
||||
//
|
||||
// RenderSurface::Blit(Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, bool alpha_blend)
|
||||
//
|
||||
// Desc: Blit a region from a Texture (Alpha == 0 -> skipped)
|
||||
//
|
||||
void RenderSurface::Blit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, bool alpha_blend) {
|
||||
Common::Point dpoint = Common::Point(_ox + dx, _oy + dy);
|
||||
if (alpha_blend) {
|
||||
_surface->transBlitFrom(src, srcRect, dpoint);
|
||||
} else {
|
||||
_surface->blitFrom(src, srcRect, dpoint);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderSurface::CrossKeyBlitMap(const Graphics::Surface& src, const Common::Rect& srcRect, int32 dx, int32 dy, const uint32* map, const uint32 key) {
|
||||
byte *dstPixels = reinterpret_cast<byte *>(_surface->getBasePtr(_ox + dx, _oy + dy));
|
||||
const byte *srcPixels = reinterpret_cast<const byte *>(src.getBasePtr(srcRect.left, srcRect.top));
|
||||
Graphics::crossKeyBlitMap(dstPixels, srcPixels, _surface->pitch, src.pitch, srcRect.width(), srcRect.height(), _surface->format.bytesPerPixel, map, key);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename uintDst, typename uintSrc>
|
||||
void inline fadedBlitLogic(uint8 *pixels, int32 pitch,
|
||||
const Common::Rect &clipWindow,
|
||||
const Graphics::PixelFormat &format,
|
||||
const Graphics::ManagedSurface &src,
|
||||
const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend) {
|
||||
int32 w = srcRect.width();
|
||||
int32 h = srcRect.height();
|
||||
|
||||
// Clamp or wrap or return?
|
||||
if (w > static_cast<int32>(src.w))
|
||||
return;
|
||||
|
||||
// Clamp or wrap or return?
|
||||
if (h > static_cast<int32>(src.h))
|
||||
return;
|
||||
|
||||
// Clip to window
|
||||
int px = dx, py = dy;
|
||||
|
||||
Common::Rect rect(dx, dy, dx + w, dy + h);
|
||||
rect.clip(clipWindow);
|
||||
dx = rect.left;
|
||||
dy = rect.top;
|
||||
w = rect.width();
|
||||
h = rect.height();
|
||||
|
||||
if (!w || !h)
|
||||
return;
|
||||
|
||||
int32 sx = srcRect.left;
|
||||
int32 sy = srcRect.top;
|
||||
|
||||
// Adjust source x and y
|
||||
if (px != dx)
|
||||
sx += dx - px;
|
||||
if (py != dy)
|
||||
sy += dy - py;
|
||||
|
||||
uint32 a = TEX32_A(col32);
|
||||
uint32 ia = 256 - a;
|
||||
uint32 r = (TEX32_R(col32) * a);
|
||||
uint32 g = (TEX32_G(col32) * a);
|
||||
uint32 b = (TEX32_B(col32) * a);
|
||||
|
||||
uint8 *dstPixels = pixels + dy * pitch + dx * sizeof(uintDst);
|
||||
int dstStep = sizeof(uintDst);
|
||||
int dstDelta = pitch - w * sizeof(uintDst);
|
||||
|
||||
const uint8 *srcPixels = reinterpret_cast<const uint8 *>(src.getBasePtr(sx, sy));
|
||||
int srcStep = sizeof(uintSrc);
|
||||
int srcDelta = src.pitch - w * sizeof(uintSrc);
|
||||
|
||||
byte palette[768];
|
||||
src.grabPalette(palette, 0, 256);
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
uint8 sa, sr, sg, sb;
|
||||
const uint32 color = *(reinterpret_cast<const uintSrc *>(srcPixels));
|
||||
if (src.format.isCLUT8()) {
|
||||
sa = 0xff;
|
||||
sr = palette[color * 3 + 0];
|
||||
sg = palette[color * 3 + 1];
|
||||
sb = palette[color * 3 + 2];
|
||||
} else {
|
||||
src.format.colorToARGB(color, sa, sr, sg, sb);
|
||||
}
|
||||
|
||||
if (sa == 0xFF || (sa && !alpha_blend)) {
|
||||
uintDst *dest = reinterpret_cast<uintDst *>(dstPixels);
|
||||
*dest = format.RGBToColor((sr * ia + r) >> 8,
|
||||
(sg * ia + g) >> 8,
|
||||
(sb * ia + b) >> 8);
|
||||
} else if (sa) {
|
||||
uintDst *dest = reinterpret_cast<uintDst *>(dstPixels);
|
||||
|
||||
uint8 r2, g2, b2;
|
||||
format.colorToRGB(*dest, r2, g2, b2);
|
||||
|
||||
uint32 dr = r2 * (256 - sa);
|
||||
uint32 dg = g2 * (256 - sa);
|
||||
uint32 db = b2 * (256 - sa);
|
||||
dr += sr * ia + ((r * sa) >> 8);
|
||||
dg += sg * ia + ((g * sa) >> 8);
|
||||
db += sb * ia + ((b * sa) >> 8);
|
||||
|
||||
*dest = format.RGBToColor(dr >> 8, dg >> 8, db >> 8);
|
||||
}
|
||||
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
//
|
||||
// void RenderSurface::FadedBlit(Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32)
|
||||
//
|
||||
// Desc: Blit a region from a Texture (Alpha == 0 -> skipped)
|
||||
//
|
||||
void RenderSurface::FadedBlit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend) {
|
||||
if (_surface->format.bytesPerPixel == 4) {
|
||||
if (src.format.bytesPerPixel == 4) {
|
||||
fadedBlitLogic<uint32, uint32>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else if (src.format.bytesPerPixel == 2) {
|
||||
fadedBlitLogic<uint32, uint16>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else if (src.format.isCLUT8()) {
|
||||
fadedBlitLogic<uint32, uint8>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else {
|
||||
error("FadedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
} else if (_surface->format.bytesPerPixel == 2) {
|
||||
if (src.format.bytesPerPixel == 4) {
|
||||
fadedBlitLogic<uint16, uint32>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else if (src.format.bytesPerPixel == 2) {
|
||||
fadedBlitLogic<uint16, uint16>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else if (src.format.isCLUT8()) {
|
||||
fadedBlitLogic<uint16, uint8>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
}
|
||||
else {
|
||||
error("FadedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
error("FadedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename uintDst, typename uintSrc>
|
||||
void inline maskedBlitLogic(uint8 *pixels, int32 pitch,
|
||||
const Common::Rect &clipWindow,
|
||||
const Graphics::PixelFormat &format,
|
||||
const Graphics::ManagedSurface &src,
|
||||
const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend) {
|
||||
int32 w = srcRect.width();
|
||||
int32 h = srcRect.height();
|
||||
|
||||
// Clamp or wrap or return?
|
||||
if (w > static_cast<int32>(src.w))
|
||||
return;
|
||||
|
||||
// Clamp or wrap or return?
|
||||
if (h > static_cast<int32>(src.h))
|
||||
return;
|
||||
|
||||
// Clip to window
|
||||
int px = dx, py = dy;
|
||||
|
||||
Common::Rect rect(dx, dy, dx + w, dy + h);
|
||||
rect.clip(clipWindow);
|
||||
dx = rect.left;
|
||||
dy = rect.top;
|
||||
w = rect.width();
|
||||
h = rect.height();
|
||||
|
||||
if (!w || !h)
|
||||
return;
|
||||
|
||||
int32 sx = srcRect.left;
|
||||
int32 sy = srcRect.top;
|
||||
|
||||
// Adjust source x and y
|
||||
if (px != dx)
|
||||
sx += dx - px;
|
||||
if (py != dy)
|
||||
sy += dy - py;
|
||||
|
||||
uint32 a = TEX32_A(col32);
|
||||
uint32 ia = 256 - a;
|
||||
uint32 r = (TEX32_R(col32) * a);
|
||||
uint32 g = (TEX32_G(col32) * a);
|
||||
uint32 b = (TEX32_B(col32) * a);
|
||||
|
||||
uint32 aMask = format.aMax() << format.aShift;
|
||||
|
||||
uint8 *dstPixels = pixels + dy * pitch + dx * sizeof(uintDst);
|
||||
int dstStep = sizeof(uintDst);
|
||||
int dstDelta = pitch - w * sizeof(uintDst);
|
||||
|
||||
const uint8 *srcPixels = reinterpret_cast<const uint8 *>(src.getBasePtr(sx, sy));
|
||||
int srcStep = sizeof(uintSrc);
|
||||
int srcDelta = src.pitch - w * sizeof(uintSrc);
|
||||
|
||||
byte palette[768];
|
||||
src.grabPalette(palette, 0, 256);
|
||||
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
uintDst *dest = reinterpret_cast<uintDst *>(dstPixels);
|
||||
if (!aMask || (*dest & aMask)) {
|
||||
uint8 sa, sr, sg, sb;
|
||||
const uint32 color = *(reinterpret_cast<const uintSrc *>(srcPixels));
|
||||
if (src.format.isCLUT8()) {
|
||||
sa = 0xff;
|
||||
sr = palette[color * 3 + 0];
|
||||
sg = palette[color * 3 + 1];
|
||||
sb = palette[color * 3 + 2];
|
||||
} else {
|
||||
src.format.colorToARGB(color, sa, sr, sg, sb);
|
||||
}
|
||||
|
||||
if (sa == 0xFF || (sa && !alpha_blend)) {
|
||||
*dest = format.RGBToColor((sr * ia + r) >> 8,
|
||||
(sg * ia + g) >> 8,
|
||||
(sb * ia + b) >> 8);
|
||||
} else if (sa) {
|
||||
uint8 r2, g2, b2;
|
||||
format.colorToRGB(*dest, r2, g2, b2);
|
||||
|
||||
uint32 dr = r2 * (256 - sa);
|
||||
uint32 dg = g2 * (256 - sa);
|
||||
uint32 db = b2 * (256 - sa);
|
||||
dr += sr * ia + ((r * sa) >> 8);
|
||||
dg += sg * ia + ((g * sa) >> 8);
|
||||
db += sb * ia + ((b * sa) >> 8);
|
||||
|
||||
*dest = format.RGBToColor(dr >> 8, dg >> 8, db >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
//
|
||||
// void RenderSurface::MaskedBlit(Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend=false)
|
||||
//
|
||||
// Desc Blit a region from a Texture with a Colour blend masked based on DestAlpha (AlphaTex == 0 || AlphaDest == 0 -> skipped. AlphaCol32 -> Blend Factors)
|
||||
//
|
||||
//
|
||||
void RenderSurface::MaskedBlit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend) {
|
||||
if (_surface->format.bytesPerPixel == 4) {
|
||||
if (src.format.bytesPerPixel == 4) {
|
||||
maskedBlitLogic<uint32, uint32>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else if (src.format.bytesPerPixel == 2) {
|
||||
maskedBlitLogic<uint32, uint16>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else if (src.format.isCLUT8()) {
|
||||
maskedBlitLogic<uint32, uint8>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else {
|
||||
error("MaskedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
} else if (_surface->format.bytesPerPixel == 2) {
|
||||
if (src.format.bytesPerPixel == 4) {
|
||||
maskedBlitLogic<uint16, uint32>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else if (src.format.bytesPerPixel == 2) {
|
||||
maskedBlitLogic<uint16, uint16>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else if (src.format.isCLUT8()) {
|
||||
maskedBlitLogic<uint16, uint8>(_pixels, _pitch, _clipWindow, _surface->format, src, srcRect, dx, dy, col32, alpha_blend);
|
||||
} else {
|
||||
error("MaskedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
} else {
|
||||
error("MaskedBlit not supported from %s to %s", src.format.toString().c_str(), _surface->format.toString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template<typename uintX>
|
||||
void inline paintLogic(uint8 *pixels, int32 pitch,
|
||||
const Common::Rect &clipWindow,
|
||||
const Graphics::PixelFormat &format,
|
||||
const ShapeFrame *frame, int32 x, int32 y, bool mirrored,
|
||||
const uint32 *map) {
|
||||
const Graphics::Surface &src = frame->getSurface();
|
||||
Common::Rect srcRect(0, 0, src.w, src.h);
|
||||
Common::Rect dstRect(x, y, x, y);
|
||||
|
||||
if (mirrored) {
|
||||
dstRect.right += frame->_xoff + 1;
|
||||
dstRect.left = dstRect.right - srcRect.width();
|
||||
|
||||
if (dstRect.left < clipWindow.left) {
|
||||
srcRect.right += dstRect.left - clipWindow.left;
|
||||
dstRect.left = clipWindow.left;
|
||||
}
|
||||
|
||||
if (dstRect.right > clipWindow.right) {
|
||||
srcRect.left += dstRect.right - clipWindow.right;
|
||||
dstRect.right = clipWindow.right;
|
||||
}
|
||||
} else {
|
||||
dstRect.left -= frame->_xoff;
|
||||
dstRect.right = dstRect.left + srcRect.width();
|
||||
|
||||
if (dstRect.left < clipWindow.left) {
|
||||
srcRect.left -= dstRect.left - clipWindow.left;
|
||||
dstRect.left = clipWindow.left;
|
||||
}
|
||||
|
||||
if (dstRect.right > clipWindow.right) {
|
||||
srcRect.right -= dstRect.right - clipWindow.right;
|
||||
dstRect.right = clipWindow.right;
|
||||
}
|
||||
}
|
||||
|
||||
dstRect.top -= frame->_yoff;
|
||||
dstRect.bottom = dstRect.top + srcRect.height();
|
||||
|
||||
if (dstRect.top < clipWindow.top) {
|
||||
srcRect.top -= dstRect.top - clipWindow.top;
|
||||
dstRect.top = clipWindow.top;
|
||||
}
|
||||
|
||||
if (dstRect.bottom > clipWindow.bottom) {
|
||||
srcRect.bottom -= dstRect.bottom - clipWindow.bottom;
|
||||
dstRect.bottom = clipWindow.bottom;
|
||||
}
|
||||
|
||||
const int srcStep = sizeof(uint8);
|
||||
int dstStep = sizeof(uintX);
|
||||
|
||||
if (mirrored) {
|
||||
x = dstRect.right - 1;
|
||||
y = dstRect.top;
|
||||
dstStep = -dstStep;
|
||||
} else {
|
||||
x = dstRect.left;
|
||||
y = dstRect.top;
|
||||
}
|
||||
|
||||
const int w = srcRect.width();
|
||||
const int h = srcRect.height();
|
||||
const int srcDelta = src.pitch - (w * srcStep);
|
||||
const int dstDelta = pitch - (w * dstStep);
|
||||
|
||||
const uint8 keycolor = frame->_keycolor;
|
||||
const uint8 *srcPixels = reinterpret_cast<const uint8 *>(src.getBasePtr(srcRect.left, srcRect.top));
|
||||
uint8 *dstPixels = reinterpret_cast<uint8 *>(pixels + x * sizeof(uintX) + pitch * y);
|
||||
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
const uint8 color = *srcPixels;
|
||||
if (color != keycolor) {
|
||||
uintX *dstpix = reinterpret_cast<uintX *>(dstPixels);
|
||||
*dstpix = static_cast<uintX>(map[color]);
|
||||
}
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename uintX>
|
||||
void inline paintBlendedLogic(uint8 *pixels, int32 pitch,
|
||||
const Common::Rect &clipWindow,
|
||||
const Graphics::PixelFormat &format,
|
||||
const ShapeFrame *frame, int32 x, int32 y,
|
||||
bool mirrored, bool invisible, uint32 highlight,
|
||||
const uint32 *map, const uint32 *xform_map) {
|
||||
const Graphics::Surface &src = frame->getSurface();
|
||||
Common::Rect srcRect(0, 0, src.w, src.h);
|
||||
Common::Rect dstRect(x, y, x, y);
|
||||
|
||||
if (mirrored) {
|
||||
dstRect.right += frame->_xoff + 1;
|
||||
dstRect.left = dstRect.right - srcRect.width();
|
||||
|
||||
if (dstRect.left < clipWindow.left) {
|
||||
srcRect.right += dstRect.left - clipWindow.left;
|
||||
dstRect.left = clipWindow.left;
|
||||
}
|
||||
|
||||
if (dstRect.right > clipWindow.right) {
|
||||
srcRect.left += dstRect.right - clipWindow.right;
|
||||
dstRect.right = clipWindow.right;
|
||||
}
|
||||
} else {
|
||||
dstRect.left -= frame->_xoff;
|
||||
dstRect.right = dstRect.left + srcRect.width();
|
||||
|
||||
if (dstRect.left < clipWindow.left) {
|
||||
srcRect.left -= dstRect.left - clipWindow.left;
|
||||
dstRect.left = clipWindow.left;
|
||||
}
|
||||
|
||||
if (dstRect.right > clipWindow.right) {
|
||||
srcRect.right -= dstRect.right - clipWindow.right;
|
||||
dstRect.right = clipWindow.right;
|
||||
}
|
||||
}
|
||||
|
||||
dstRect.top -= frame->_yoff;
|
||||
dstRect.bottom = dstRect.top + srcRect.height();
|
||||
|
||||
if (dstRect.top < clipWindow.top) {
|
||||
srcRect.top -= dstRect.top - clipWindow.top;
|
||||
dstRect.top = clipWindow.top;
|
||||
}
|
||||
|
||||
if (dstRect.bottom > clipWindow.bottom) {
|
||||
srcRect.bottom -= dstRect.bottom - clipWindow.bottom;
|
||||
dstRect.bottom = clipWindow.bottom;
|
||||
}
|
||||
|
||||
const int srcStep = sizeof(uint8);
|
||||
int dstStep = sizeof(uintX);
|
||||
|
||||
if (mirrored) {
|
||||
x = dstRect.right - 1;
|
||||
y = dstRect.top;
|
||||
dstStep = -dstStep;
|
||||
} else {
|
||||
x = dstRect.left;
|
||||
y = dstRect.top;
|
||||
}
|
||||
|
||||
const int w = srcRect.width();
|
||||
const int h = srcRect.height();
|
||||
const int srcDelta = src.pitch - (w * srcStep);
|
||||
const int dstDelta = pitch - (w * dstStep);
|
||||
|
||||
const uint8 keycolor = frame->_keycolor;
|
||||
const uint8 *srcPixels = reinterpret_cast<const uint8 *>(src.getBasePtr(srcRect.left, srcRect.top));
|
||||
uint8 *dstPixels = reinterpret_cast<uint8 *>(pixels + x * sizeof(uintX) + pitch * y);
|
||||
|
||||
uint8 dr, dg, db;
|
||||
uint8 sr, sg, sb;
|
||||
|
||||
if (highlight) {
|
||||
uint32 ca = TEX32_A(highlight);
|
||||
uint32 cr = TEX32_R(highlight);
|
||||
uint32 cg = TEX32_G(highlight);
|
||||
uint32 cb = TEX32_B(highlight);
|
||||
uint32 ica = 255 - ca;
|
||||
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
const uint8 color = *srcPixels;
|
||||
if (color != keycolor) {
|
||||
uintX *dstpix = reinterpret_cast<uintX *>(dstPixels);
|
||||
format.colorToRGB(*dstpix, dr, dg, db);
|
||||
|
||||
if (xform_map && xform_map[color]) {
|
||||
uint32 val = xform_map[color];
|
||||
|
||||
uint32 ia = 256 - TEX32_A(val);
|
||||
uint32 r = (dr * ia + 256 * TEX32_R(val)) >> 8;
|
||||
uint32 g = (dg * ia + 256 * TEX32_G(val)) >> 8;
|
||||
uint32 b = (db * ia + 256 * TEX32_B(val)) >> 8;
|
||||
|
||||
sr = r > 0xFF ? 0xFF : r;
|
||||
sg = g > 0xFF ? 0xFF : g;
|
||||
sb = b > 0xFF ? 0xFF : b;
|
||||
} else {
|
||||
format.colorToRGB(map[color], sr, sg, sb);
|
||||
}
|
||||
|
||||
if (invisible) {
|
||||
dr = (((sr * ica + cr * ca) >> 1) + (dr << 7)) >> 8;
|
||||
dg = (((sg * ica + cg * ca) >> 1) + (dg << 7)) >> 8;
|
||||
db = (((sb * ica + cb * ca) >> 1) + (db << 7)) >> 8;
|
||||
} else {
|
||||
dr = (sr * ica + cr * ca) >> 8;
|
||||
dg = (sg * ica + cg * ca) >> 8;
|
||||
db = (sb * ica + cb * ca) >> 8;
|
||||
}
|
||||
*dstpix = static_cast<uintX>(format.RGBToColor(dr, dg, db));
|
||||
}
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
} else if (invisible) {
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
const uint8 color = *srcPixels;
|
||||
if (color != keycolor) {
|
||||
uintX *dstpix = reinterpret_cast<uintX *>(dstPixels);
|
||||
format.colorToRGB(*dstpix, dr, dg, db);
|
||||
|
||||
if (xform_map && xform_map[color]) {
|
||||
uint32 val = xform_map[color];
|
||||
|
||||
uint32 ia = 256 - TEX32_A(val);
|
||||
uint32 r = (dr * ia + 256 * TEX32_R(val)) >> 8;
|
||||
uint32 g = (dg * ia + 256 * TEX32_G(val)) >> 8;
|
||||
uint32 b = (db * ia + 256 * TEX32_B(val)) >> 8;
|
||||
|
||||
sr = r > 0xFF ? 0xFF : r;
|
||||
sg = g > 0xFF ? 0xFF : g;
|
||||
sb = b > 0xFF ? 0xFF : b;
|
||||
} else {
|
||||
format.colorToRGB(map[color], sr, sg, sb);
|
||||
}
|
||||
|
||||
dr = (sr * 128 + dr * 128) >> 8;
|
||||
dg = (sg * 128 + dg * 128) >> 8,
|
||||
db = (sb * 128 + db * 128) >> 8;
|
||||
|
||||
*dstpix = static_cast<uintX>(format.RGBToColor(dr, dg, db));
|
||||
}
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++) {
|
||||
const uint8 color = *srcPixels;
|
||||
if (color != keycolor) {
|
||||
uintX *dstpix = reinterpret_cast<uintX *>(dstPixels);
|
||||
if (xform_map && xform_map[color]) {
|
||||
format.colorToRGB(*dstpix, dr, dg, db);
|
||||
|
||||
uint32 val = xform_map[color];
|
||||
uint32 ia = 256 - TEX32_A(val);
|
||||
uint32 r = (dr * ia + 256 * TEX32_R(val)) >> 8;
|
||||
uint32 g = (dg * ia + 256 * TEX32_G(val)) >> 8;
|
||||
uint32 b = (db * ia + 256 * TEX32_B(val)) >> 8;
|
||||
|
||||
dr = r > 0xFF ? 0xFF : r;
|
||||
dg = g > 0xFF ? 0xFF : g;
|
||||
db = b > 0xFF ? 0xFF : b;
|
||||
*dstpix = static_cast<uintX>(format.RGBToColor(dr, dg, db));
|
||||
} else {
|
||||
*dstpix = static_cast<uintX>(map[color]);
|
||||
}
|
||||
}
|
||||
srcPixels += srcStep;
|
||||
dstPixels += dstStep;
|
||||
}
|
||||
|
||||
srcPixels += srcDelta;
|
||||
dstPixels += dstDelta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of anonymous namespace
|
||||
|
||||
//
|
||||
// void RenderSurface::Paint(Shape*s, uint32 framenum, int32 x, int32 y, bool mirrored)
|
||||
//
|
||||
// Desc: Standard shape drawing functions. Clips but doesn't do anything else
|
||||
//
|
||||
void RenderSurface::Paint(const Shape *s, uint32 framenum, int32 x, int32 y, bool mirrored) {
|
||||
const ShapeFrame *frame = s->getFrame(framenum);
|
||||
if (!frame || !s->getPalette())
|
||||
return;
|
||||
|
||||
const uint32 *map = s->getPalette()->_native;
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
paintLogic<uint32>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, map);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
paintLogic<uint16>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, map);
|
||||
else if (_surface->format.isCLUT8())
|
||||
paintLogic<uint8>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, map);
|
||||
else
|
||||
error("Paint not supported for surface format: %s", _surface->format.toString().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::PaintTranslucent(Shape*s, uint32 framenum, int32 x, int32 y, bool mirrored)
|
||||
//
|
||||
// Desc: Standard shape drawing functions. Clips and XForms
|
||||
//
|
||||
void RenderSurface::PaintTranslucent(const Shape *s, uint32 framenum, int32 x, int32 y, bool mirrored) {
|
||||
const ShapeFrame *frame = s->getFrame(framenum);
|
||||
if (!frame || !s->getPalette())
|
||||
return;
|
||||
|
||||
const uint32 *map = s->getPalette()->_native;
|
||||
const uint32 *xform_map = s->getPalette()->_xform;
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
paintBlendedLogic<uint32>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, false, 0, map, xform_map);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
paintBlendedLogic<uint16>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, false, 0, map, xform_map);
|
||||
else
|
||||
error("PaintTranslucent not supported for surface format: %s", _surface->format.toString().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::PaintInvisible(Shape* s, uint32 frame, int32 x, int32 y, bool mirrored)
|
||||
//
|
||||
// Desc: Standard shape drawing functions. Invisible, Clips, and conditionally Flips and Xforms
|
||||
//
|
||||
void RenderSurface::PaintInvisible(const Shape *s, uint32 framenum, int32 x, int32 y, bool trans, bool mirrored) {
|
||||
const ShapeFrame *frame = s->getFrame(framenum);
|
||||
if (!frame || !s->getPalette())
|
||||
return;
|
||||
|
||||
const uint32 *map = s->getPalette()->_native;
|
||||
const uint32 *xform_map = trans ? s->getPalette()->_xform : nullptr;
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
paintBlendedLogic<uint32>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, true, 0, map, xform_map);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
paintBlendedLogic<uint16>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, true, 0, map, xform_map);
|
||||
else
|
||||
error("PaintInvisible not supported for surface format: %s", _surface->format.toString().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::PaintHighlight(Shape* s, uint32 frame, int32 x, int32 y, bool mirrored)
|
||||
//
|
||||
// Desc: Standard shape drawing functions. Highlights, Clips, and conditionally Flips and Xforms
|
||||
//
|
||||
void RenderSurface::PaintHighlight(const Shape *s, uint32 framenum, int32 x, int32 y, bool trans, bool mirrored, uint32 col32) {
|
||||
const ShapeFrame *frame = s->getFrame(framenum);
|
||||
if (!frame || !s->getPalette())
|
||||
return;
|
||||
|
||||
const uint32 *map = s->getPalette()->_native;
|
||||
const uint32 *xform_map = trans ? s->getPalette()->_xform : nullptr;
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
paintBlendedLogic<uint32>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, false, col32, map, xform_map);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
paintBlendedLogic<uint16>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, false, col32, map, xform_map);
|
||||
else
|
||||
error("PaintHighlight not supported for surface format: %s", _surface->format.toString().c_str());
|
||||
}
|
||||
|
||||
//
|
||||
// void RenderSurface::PaintHighlightInvis(Shape* s, uint32 frame, int32 x, int32 y, bool mirrored)
|
||||
//
|
||||
// Desc: Standard shape drawing functions. Highlights, Clips, and conditionally Flips and Xforms. 50% translucent
|
||||
//
|
||||
void RenderSurface::PaintHighlightInvis(const Shape *s, uint32 framenum, int32 x, int32 y, bool trans, bool mirrored, uint32 col32) {
|
||||
const ShapeFrame *frame = s->getFrame(framenum);
|
||||
if (!frame || !s->getPalette())
|
||||
return;
|
||||
|
||||
const uint32 *map = s->getPalette()->_native;
|
||||
const uint32 *xform_map = trans ? s->getPalette()->_xform : nullptr;
|
||||
|
||||
if (_surface->format.bytesPerPixel == 4)
|
||||
paintBlendedLogic<uint32>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, true, col32, map, xform_map);
|
||||
else if (_surface->format.bytesPerPixel == 2)
|
||||
paintBlendedLogic<uint16>(_pixels, _pitch, _clipWindow, _surface->format, frame, x, y, mirrored, true, col32, map, xform_map);
|
||||
else
|
||||
error("PaintHighlightInvis not supported for surface format: %s", _surface->format.toString().c_str());
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
185
engines/ultima/ultima8/gfx/render_surface.h
Normal file
185
engines/ultima/ultima8/gfx/render_surface.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_RENDERSURFACE_H
|
||||
#define ULTIMA8_GFX_RENDERSURFACE_H
|
||||
|
||||
#include "graphics/managed_surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Shape;
|
||||
|
||||
//
|
||||
// RenderSurface
|
||||
//
|
||||
// Desc: The base class for rendering in Pentagram
|
||||
//
|
||||
class RenderSurface {
|
||||
private:
|
||||
// Frame buffer
|
||||
uint8 *_pixels; // Pointer to logical pixel 0,0
|
||||
|
||||
// Dimensions
|
||||
int32 _ox, _oy; // Physical Pixel for Logical Origin
|
||||
int32 _pitch; // Frame buffer pitch (bytes) (could be negated)
|
||||
bool _flipped;
|
||||
|
||||
// Clipping Rectangle
|
||||
Common::Rect _clipWindow;
|
||||
|
||||
// Locking count
|
||||
uint32 _lockCount; // Number of locks on surface
|
||||
|
||||
Graphics::ManagedSurface *_surface;
|
||||
DisposeAfterUse::Flag _disposeAfterUse;
|
||||
|
||||
// Update the Pixels Pointer
|
||||
void SetPixelsPointer();
|
||||
|
||||
public:
|
||||
// Create a render surface
|
||||
RenderSurface(int width, int height, const Graphics::PixelFormat &format);
|
||||
|
||||
// Create from a managed surface
|
||||
RenderSurface(Graphics::ManagedSurface *s, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
|
||||
|
||||
~RenderSurface();
|
||||
|
||||
//
|
||||
// Being/End Painting
|
||||
//
|
||||
|
||||
//! Begin painting to the buffer. MUST BE CALLED BEFORE DOING ANYTHING TO THE SURFACE!
|
||||
// \note Can be called multiple times
|
||||
// \return true on success, false on failure
|
||||
bool BeginPainting();
|
||||
|
||||
//! Finish paining to the buffer.
|
||||
// \note MUST BE CALLED FOR EACH CALL TO BeginPainting()
|
||||
// \return true on success, false on failure
|
||||
bool EndPainting();
|
||||
|
||||
//
|
||||
// Surface Properties
|
||||
//
|
||||
|
||||
//! Set the Origin of the Surface
|
||||
void SetOrigin(int32 x, int32 y);
|
||||
|
||||
//! Set the Origin of the Surface
|
||||
void GetOrigin(int32 &x, int32 &y) const;
|
||||
|
||||
//! Get the Surface Dimensions
|
||||
Common::Rect32 getSurfaceDims() const;
|
||||
|
||||
//! Get Clipping Rectangle
|
||||
Common::Rect32 getClippingRect() const;
|
||||
|
||||
//! Set Clipping Rectangle
|
||||
void setClippingRect(const Common::Rect32 &);
|
||||
|
||||
//! Flip the surface
|
||||
void SetFlipped(bool flipped);
|
||||
|
||||
//! Has the render surface been flipped?
|
||||
bool IsFlipped() const;
|
||||
|
||||
//! Get a reference to the underlying surface that's being encapsulated
|
||||
Graphics::ManagedSurface *getRawSurface() const {
|
||||
return _surface;
|
||||
};
|
||||
|
||||
//! Fill the region with a color in the pixel format
|
||||
void fillRect(const Common::Rect32 &r, uint32 color);
|
||||
|
||||
//! Fill the region with a color in the pixel format
|
||||
void frameRect(const Common::Rect32 &r, uint32 color);
|
||||
|
||||
// Draw a line with a color in the pixel format
|
||||
void drawLine(int32 sx, int32 sy, int32 ex, int32 ey, uint32 color);
|
||||
|
||||
//! Fill the region with a color in the TEX32_PACK_RGB format
|
||||
void fill32(uint32 rgb, int32 sx, int32 sy, int32 w, int32 h) {
|
||||
fill32(rgb, Common::Rect32(sx, sy, sx + w, sy + h));
|
||||
}
|
||||
|
||||
//! Fill the region with a color in the TEX32_PACK_RGB format
|
||||
void fill32(uint32 rgb, const Common::Rect32 &r);
|
||||
|
||||
//! Fill the region doing alpha blending with a color in the TEX32_PACK_RGBA format
|
||||
void fillBlended(uint32 rgba, const Common::Rect32 &r);
|
||||
|
||||
//! Fill the region with a color in the TEX32_PACK_RGB format
|
||||
void frameRect32(uint32 rgb, const Common::Rect32 &r);
|
||||
|
||||
// Draw a line with a color in the TEX32_PACK_RGB format
|
||||
void drawLine32(uint32 rgb, int32 sx, int32 sy, int32 ex, int32 ey);
|
||||
|
||||
//
|
||||
// The rule for painting methods:
|
||||
//
|
||||
// First arg are the source object to 'draw' with
|
||||
// Next args are any other required data to define the 'source'
|
||||
// Next args are the destination position
|
||||
//
|
||||
|
||||
//
|
||||
// Basic Shape Painting
|
||||
//
|
||||
|
||||
//! Paint a Shape
|
||||
void Paint(const Shape *s, uint32 frame, int32 x, int32 y, bool mirrored = false);
|
||||
|
||||
//! Paint a Translucent Shape.
|
||||
void PaintTranslucent(const Shape *s, uint32 frame, int32 x, int32 y, bool mirrored = false);
|
||||
|
||||
//! Paint an Invisible Shape
|
||||
void PaintInvisible(const Shape *s, uint32 frame, int32 x, int32 y, bool trans, bool mirrored);
|
||||
|
||||
//! Paint a Highlighted Shape of using the 32 Bit Colour col32 (0xAARRGGBB Alpha is blend level)
|
||||
void PaintHighlight(const Shape *s, uint32 frame, int32 x, int32 y, bool trans, bool mirrored, uint32 col32);
|
||||
|
||||
//! Paint a Invisible Highlighted Shape of using the 32 Bit Colour col32 (0xAARRGGBB Alpha is blend level)
|
||||
void PaintHighlightInvis(const Shape *s, uint32 frame, int32 x, int32 y, bool trans, bool mirrored, uint32 col32);
|
||||
|
||||
//
|
||||
// Basic Texture Blitting
|
||||
//
|
||||
|
||||
//! Blit a region from a Texture (Alpha == 0 -> skipped)
|
||||
void Blit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, bool alpha_blend = false);
|
||||
|
||||
void CrossKeyBlitMap(const Graphics::Surface &src, const Common::Rect &srcRect, int32 dx, int32 dy, const uint32 *map, const uint32 key);
|
||||
|
||||
//! Blit a region from a Texture with a Colour blend (AlphaTex == 0 -> skipped. AlphaCol32 -> Blend Factors)
|
||||
void FadedBlit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend = false);
|
||||
|
||||
//! Blit a region from a Texture with a Colour blend masked based on DestAlpha (AlphaTex == 0 || AlphaDest == 0 -> skipped. AlphaCol32 -> Blend Factors)
|
||||
void MaskedBlit(const Graphics::ManagedSurface &src, const Common::Rect &srcRect, int32 dx, int32 dy, uint32 col32, bool alpha_blend = false);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
286
engines/ultima/ultima8/gfx/shape.cpp
Normal file
286
engines/ultima/ultima8/gfx/shape.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/raw_shape_frame.h"
|
||||
#include "ultima/ultima8/convert/u8/convert_shape_u8.h"
|
||||
#include "ultima/ultima8/convert/crusader/convert_shape_crusader.h"
|
||||
#include "ultima/ultima8/misc/stream_util.h"
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
Shape::Shape(const uint8 *data, uint32 size, const ConvertShapeFormat *format,
|
||||
const uint16 id, const uint32 shape)
|
||||
: _flexId(id), _shapeNum(shape), _palette(nullptr) {
|
||||
// NB: U8 style!
|
||||
loadFrames(data, size, format);
|
||||
|
||||
delete[] const_cast<uint8 *>(data);
|
||||
}
|
||||
|
||||
Shape::Shape(Common::SeekableReadStream *src, const ConvertShapeFormat *format)
|
||||
: _flexId(0), _shapeNum(0), _palette(nullptr) {
|
||||
// NB: U8 style!
|
||||
uint32 size = src->size();
|
||||
uint8 *data = new uint8[size];
|
||||
src->read(data, size);
|
||||
|
||||
loadFrames(data, size, format);
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
Shape::~Shape() {
|
||||
for (uint i = 0; i < _frames.size(); ++i)
|
||||
delete _frames[i];
|
||||
}
|
||||
|
||||
void Shape::loadFrames(const uint8 *data, uint32 size, const ConvertShapeFormat *format) {
|
||||
if (!format)
|
||||
format = DetectShapeFormat(data, size);
|
||||
|
||||
if (!format) {
|
||||
// Should be fatal?
|
||||
warning("Unable to detect shape format");
|
||||
return;
|
||||
}
|
||||
|
||||
Common::Array<RawShapeFrame *> rawframes;
|
||||
// Load it as u8
|
||||
|
||||
if (format == &U8ShapeFormat || format == &U82DShapeFormat)
|
||||
rawframes = loadU8Format(data, size, format);
|
||||
else if (format == &PentagramShapeFormat)
|
||||
rawframes = loadPentagramFormat(data, size, format);
|
||||
else
|
||||
rawframes = loadGenericFormat(data, size, format);
|
||||
|
||||
for (uint i = 0; i < rawframes.size(); i++) {
|
||||
_frames.push_back(new ShapeFrame(rawframes[i]));
|
||||
delete rawframes[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Shape::getShapeId(uint16 &id, uint32 &shape) const {
|
||||
id = _flexId;
|
||||
shape = _shapeNum;
|
||||
}
|
||||
|
||||
// This will load a u8 style shape 'optimized'.
|
||||
Common::Array<RawShapeFrame *> Shape::loadU8Format(const uint8 *data, uint32 size, const ConvertShapeFormat *format) {
|
||||
Common::MemoryReadStream stream(data, size);
|
||||
stream.skip(4); // skip header
|
||||
unsigned int framecount = stream.readUint16LE();
|
||||
|
||||
Common::Array<RawShapeFrame *> frames;
|
||||
|
||||
if (framecount == 0) {
|
||||
return loadGenericFormat(data, size, format);
|
||||
}
|
||||
|
||||
frames.reserve(framecount);
|
||||
|
||||
for (uint i = 0; i < framecount; ++i) {
|
||||
uint32 frameoffset = stream.readUint32LE() & 0xFFFFFF;
|
||||
uint32 framesize = stream.readUint16LE();
|
||||
|
||||
frames.push_back(new RawShapeFrame(data + frameoffset, framesize, format));
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
// This will load a pentagram style shape 'optimized'.
|
||||
Common::Array<RawShapeFrame *> Shape::loadPentagramFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format) {
|
||||
Common::MemoryReadStream stream(data, size);
|
||||
stream.skip(4); // skip header
|
||||
unsigned int framecount = stream.readUint16LE();
|
||||
Common::Array<RawShapeFrame *> frames;
|
||||
|
||||
if (framecount == 0) {
|
||||
return loadGenericFormat(data, size, format);
|
||||
}
|
||||
|
||||
frames.reserve(framecount);
|
||||
|
||||
for (uint i = 0; i < framecount; ++i) {
|
||||
uint32 frameoffset = stream.readUint32LE();
|
||||
uint32 framesize = stream.readUint32LE();
|
||||
|
||||
frames.push_back(new RawShapeFrame(data + frameoffset, framesize, format));
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
// This will load any sort of shape via a ConvertShapeFormat struct
|
||||
Common::Array<RawShapeFrame *> Shape::loadGenericFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format) {
|
||||
uint32 framecount;
|
||||
uint32 frameoffset;
|
||||
uint32 framesize;
|
||||
Common::MemoryReadStream ds(data, size);
|
||||
|
||||
Common::Array<RawShapeFrame *> frames;
|
||||
|
||||
if (format->_bytes_ident) {
|
||||
uint8 *ident = new uint8[format->_bytes_ident];
|
||||
ds.read(ident, format->_bytes_ident);
|
||||
bool match = memcmp(ident, format->_ident, format->_bytes_ident) == 0;
|
||||
delete[] ident;
|
||||
|
||||
if (!match) {
|
||||
frames.clear();
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
||||
// Read special buffer
|
||||
uint8 special[256];
|
||||
if (format->_bytes_special) {
|
||||
memset(special, 0, 256);
|
||||
for (uint32 i = 0; i < format->_bytes_special; i++) special[ds.readByte() & 0xFF] = i + 2;
|
||||
}
|
||||
|
||||
// Skip unknown
|
||||
if (format->_bytes_header_unk && format != &Crusader2DShapeFormat) {
|
||||
//uint32 val =
|
||||
readX(ds, format->_bytes_header_unk);
|
||||
//uint16 lowval = val & 0xff;
|
||||
//uint16 highval = (val >> 16) & 0xff;
|
||||
//uint32 dummy = 0 + lowval + highval + val;
|
||||
} else {
|
||||
// Appears to be shape Width x Height for Crusader 2D shapes,
|
||||
// not needed - we get them by frame.
|
||||
ds.skip(format->_bytes_header_unk);
|
||||
}
|
||||
|
||||
// Read framecount, default 1 if no
|
||||
if (format->_bytes_num_frames) framecount = readX(ds, format->_bytes_num_frames);
|
||||
else framecount = 1;
|
||||
if (framecount == 0) framecount = ConvertShape::CalcNumFrames(ds, format, size, 0);
|
||||
|
||||
frames.reserve(framecount);
|
||||
|
||||
for (uint i = 0; i < framecount; ++i) {
|
||||
// Read the offset
|
||||
if (format->_bytes_frame_offset) frameoffset = readX(ds, format->_bytes_frame_offset) + format->_bytes_special;
|
||||
else frameoffset = format->_len_header + (format->_len_frameheader * i);
|
||||
|
||||
// Skip the unknown
|
||||
if (format->_bytes_frameheader_unk) {
|
||||
readX(ds, format->_bytes_frameheader_unk);
|
||||
}
|
||||
|
||||
// Read frame_length
|
||||
if (format->_bytes_frame_length) framesize = readX(ds, format->_bytes_frame_length) + format->_bytes_frame_length_kludge;
|
||||
else framesize = size - frameoffset;
|
||||
|
||||
if (framesize > size) {
|
||||
warning("shape frame %d goes off the end of the buffer, stopping early", i);
|
||||
break;
|
||||
}
|
||||
|
||||
ConvertShapeFrame *prev = nullptr, p;
|
||||
|
||||
if (format->_bytes_special && i > 0) {
|
||||
prev = &p;
|
||||
frames[i - 1]->getConvertShapeFrame(p);
|
||||
}
|
||||
|
||||
frames.push_back(new RawShapeFrame(data + frameoffset, framesize, format, special, prev));
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
// This will detect the format of a shape
|
||||
const ConvertShapeFormat *Shape::DetectShapeFormat(const uint8 *data, uint32 size) {
|
||||
Common::MemoryReadStream ds(data, size);
|
||||
return Shape::DetectShapeFormat(ds, size);
|
||||
}
|
||||
|
||||
const ConvertShapeFormat *Shape::DetectShapeFormat(Common::SeekableReadStream &ds, uint32 size) {
|
||||
const ConvertShapeFormat *ret = nullptr;
|
||||
|
||||
if (ConvertShape::CheckUnsafe(ds, &PentagramShapeFormat, size))
|
||||
ret = &PentagramShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &U8SKFShapeFormat, size))
|
||||
ret = &U8SKFShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &U8ShapeFormat, size))
|
||||
ret = &U8ShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &U82DShapeFormat, size))
|
||||
ret = &U82DShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &CrusaderShapeFormat, size))
|
||||
ret = &CrusaderShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &Crusader2DShapeFormat, size))
|
||||
ret = &Crusader2DShapeFormat;
|
||||
else if (ConvertShape::CheckUnsafe(ds, &U8CMPShapeFormat, size))
|
||||
ret = &U8CMPShapeFormat;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Shape::getTotalDimensions(int32 &w, int32 &h, int32 &x, int32 &y) const {
|
||||
if (_frames.empty()) {
|
||||
w = 0;
|
||||
h = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int32 minx = 1000000, maxx = -1000000;
|
||||
int32 miny = 1000000, maxy = -1000000;
|
||||
|
||||
for (uint i = 0; i < _frames.size(); ++i) {
|
||||
ShapeFrame *frame = _frames[i];
|
||||
if (-frame->_xoff < minx)
|
||||
minx = -frame->_xoff;
|
||||
if (-frame->_yoff < miny)
|
||||
miny = -frame->_yoff;
|
||||
if (frame->_width - frame->_xoff - 1 > maxx)
|
||||
maxx = frame->_width - frame->_xoff - 1;
|
||||
if (frame->_height - frame->_yoff - 1 > maxy)
|
||||
maxy = frame->_height - frame->_yoff - 1;
|
||||
}
|
||||
|
||||
w = maxx - minx + 1;
|
||||
h = maxy - miny + 1;
|
||||
x = -minx;
|
||||
y = -miny;
|
||||
}
|
||||
|
||||
const ShapeFrame *Shape::getFrame(unsigned int frame) const {
|
||||
if (frame < _frames.size())
|
||||
return _frames[frame];
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
94
engines/ultima/ultima8/gfx/shape.h
Normal file
94
engines/ultima/ultima8/gfx/shape.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_SHAPE_H
|
||||
#define ULTIMA8_GFX_SHAPE_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeFrame;
|
||||
class RawShapeFrame;
|
||||
class Palette;
|
||||
struct ConvertShapeFormat;
|
||||
|
||||
class Shape {
|
||||
public:
|
||||
// Parse data, create frames.
|
||||
// NB: Shape uses data without copying it. It is deleted on destruction
|
||||
// If format is not specified it will be autodetected
|
||||
Shape(const uint8 *data, uint32 size, const ConvertShapeFormat *format,
|
||||
const uint16 flexId, const uint32 shapenum);
|
||||
Shape(Common::SeekableReadStream *src, const ConvertShapeFormat *format);
|
||||
virtual ~Shape();
|
||||
void setPalette(const Palette *pal) {
|
||||
_palette = pal;
|
||||
}
|
||||
const Palette *getPalette() const {
|
||||
return _palette;
|
||||
}
|
||||
|
||||
uint32 frameCount() const {
|
||||
return static_cast<uint32>(_frames.size());
|
||||
}
|
||||
|
||||
//! Returns the dimensions of all frames combined
|
||||
//! (w,h) = size of smallest rectangle covering all frames
|
||||
//! (x,y) = coordinates of origin relative to top-left point of rectangle
|
||||
void getTotalDimensions(int32 &w, int32 &h, int32 &x, int32 &y) const;
|
||||
|
||||
const ShapeFrame *getFrame(unsigned int frame) const;
|
||||
|
||||
void getShapeId(uint16 &flexId, uint32 &shapenum) const;
|
||||
|
||||
// This will detect the format of a shape
|
||||
static const ConvertShapeFormat *DetectShapeFormat(const uint8 *data, uint32 size);
|
||||
static const ConvertShapeFormat *DetectShapeFormat(Common::SeekableReadStream &ds, uint32 size);
|
||||
|
||||
private:
|
||||
void loadFrames(const uint8 *data, uint32 size, const ConvertShapeFormat *format);
|
||||
|
||||
// This will load a u8 style shape 'optimized'.
|
||||
static Common::Array<RawShapeFrame *> loadU8Format(const uint8 *data, uint32 size, const ConvertShapeFormat *format);
|
||||
|
||||
// This will load a pentagram style shape 'optimized'.
|
||||
static Common::Array<RawShapeFrame *> loadPentagramFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format);
|
||||
|
||||
// This will load any sort of shape via a ConvertShapeFormat struct
|
||||
// Crusader shapes must be loaded this way
|
||||
static Common::Array<RawShapeFrame *> loadGenericFormat(const uint8 *data, uint32 size, const ConvertShapeFormat *format);
|
||||
|
||||
Common::Array<ShapeFrame *> _frames;
|
||||
|
||||
const Palette *_palette;
|
||||
|
||||
const uint16 _flexId;
|
||||
const uint32 _shapeNum;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
87
engines/ultima/ultima8/gfx/shape_archive.cpp
Normal file
87
engines/ultima/ultima8/gfx/shape_archive.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/convert/convert_shape.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ShapeArchive::~ShapeArchive() {
|
||||
Archive::uncache();
|
||||
}
|
||||
|
||||
Shape *ShapeArchive::getShape(uint32 shapenum) {
|
||||
if (shapenum >= _count)
|
||||
return nullptr;
|
||||
cache(shapenum);
|
||||
|
||||
return _shapes[shapenum];
|
||||
}
|
||||
|
||||
void ShapeArchive::cache(uint32 shapenum) {
|
||||
if (shapenum >= _count) return;
|
||||
if (_shapes.empty()) _shapes.resize(_count);
|
||||
|
||||
if (_shapes[shapenum]) return;
|
||||
|
||||
uint32 shpsize;
|
||||
uint8 *data = getRawObject(shapenum, &shpsize);
|
||||
|
||||
if (!data || shpsize == 0) return;
|
||||
|
||||
// Auto detect format
|
||||
if (!_format) {
|
||||
_format = Shape::DetectShapeFormat(data, shpsize);
|
||||
}
|
||||
|
||||
if (!_format) {
|
||||
delete [] data;
|
||||
warning("Unable to detect shape format for flex.");
|
||||
return;
|
||||
}
|
||||
|
||||
Shape *shape = new Shape(data, shpsize, _format, _id, shapenum);
|
||||
if (_palette) shape->setPalette(_palette);
|
||||
|
||||
_shapes[shapenum] = shape;
|
||||
}
|
||||
|
||||
void ShapeArchive::uncache(uint32 shapenum) {
|
||||
if (shapenum >= _count) return;
|
||||
if (_shapes.empty()) return;
|
||||
|
||||
delete _shapes[shapenum];
|
||||
_shapes[shapenum] = nullptr;
|
||||
}
|
||||
|
||||
bool ShapeArchive::isCached(uint32 shapenum) const {
|
||||
if (shapenum >= _count) return false;
|
||||
if (_shapes.empty()) return false;
|
||||
|
||||
return (_shapes[shapenum] != nullptr);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
61
engines/ultima/ultima8/gfx/shape_archive.h
Normal file
61
engines/ultima/ultima8/gfx/shape_archive.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_SHAPEARCHIVE_H
|
||||
#define ULTIMA8_GFX_SHAPEARCHIVE_H
|
||||
|
||||
#include "ultima/ultima8/filesys/archive.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class Shape;
|
||||
struct ConvertShapeFormat;
|
||||
class Palette;
|
||||
|
||||
class ShapeArchive : public Archive {
|
||||
public:
|
||||
ShapeArchive(uint16 id, const Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: Archive(), _id(id), _format(format), _palette(pal) { }
|
||||
ShapeArchive(Common::SeekableReadStream *rs, uint16 id, const Palette *pal = 0,
|
||||
const ConvertShapeFormat *format = 0)
|
||||
: Archive(rs), _id(id), _format(format), _palette(pal) { }
|
||||
|
||||
~ShapeArchive() override;
|
||||
|
||||
Shape *getShape(uint32 shapenum);
|
||||
|
||||
void cache(uint32 shapenum) override;
|
||||
void uncache(uint32 shapenum) override;
|
||||
bool isCached(uint32 shapenum) const override;
|
||||
|
||||
protected:
|
||||
uint16 _id;
|
||||
const ConvertShapeFormat *_format;
|
||||
const Palette *_palette;
|
||||
Std::vector<Shape *> _shapes;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
119
engines/ultima/ultima8/gfx/shape_frame.cpp
Normal file
119
engines/ultima/ultima8/gfx/shape_frame.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_frame.h"
|
||||
#include "ultima/ultima8/gfx/raw_shape_frame.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
ShapeFrame::ShapeFrame(const RawShapeFrame *rawframe) :
|
||||
_width(_surface.w), _height(_surface.h),
|
||||
_xoff(rawframe->_xoff), _yoff(rawframe->_yoff),
|
||||
_keycolor(0xFF) {
|
||||
|
||||
_surface.create(rawframe->_width, rawframe->_height, Graphics::PixelFormat::createFormatCLUT8());
|
||||
|
||||
// load adjusting keycolor until success
|
||||
if (!load(rawframe, _keycolor)) {
|
||||
_keycolor = 0;
|
||||
while (!load(rawframe, _keycolor) && _keycolor < 0xFF) {
|
||||
_keycolor++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapeFrame::~ShapeFrame() {
|
||||
_surface.free();
|
||||
}
|
||||
|
||||
bool ShapeFrame::load(const RawShapeFrame *rawframe, uint8 keycolor) {
|
||||
bool result = true;
|
||||
uint8 *pixels = reinterpret_cast<uint8 *>(_surface.getPixels());
|
||||
memset(pixels, keycolor, _surface.w * _surface.h);
|
||||
|
||||
for (int y = 0; y < _surface.h; y++) {
|
||||
int32 xpos = 0;
|
||||
const uint8 *linedata = rawframe->_rle_data + rawframe->_line_offsets[y];
|
||||
|
||||
do {
|
||||
xpos += *linedata++;
|
||||
|
||||
if (xpos >= _surface.w)
|
||||
break;
|
||||
|
||||
int32 dlen = *linedata++;
|
||||
int type = 0;
|
||||
|
||||
if (rawframe->_compressed) {
|
||||
type = dlen & 1;
|
||||
dlen >>= 1;
|
||||
}
|
||||
|
||||
for (int doff = 0; doff < dlen; doff++) {
|
||||
if (*linedata == keycolor)
|
||||
result = false;
|
||||
pixels[y * _surface.w + xpos + doff] = *linedata;
|
||||
if (!type) {
|
||||
linedata++;
|
||||
}
|
||||
}
|
||||
|
||||
xpos += dlen;
|
||||
if (type) {
|
||||
linedata++;
|
||||
}
|
||||
|
||||
} while (xpos < _surface.w);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Checks to see if the frame has a pixel at the point
|
||||
bool ShapeFrame::hasPoint(int x, int y) const {
|
||||
// Add the offset
|
||||
x += _xoff;
|
||||
y += _yoff;
|
||||
|
||||
// First gross culling based on dims
|
||||
if (x < 0 || y < 0 || x >= _surface.w || y >= _surface.h)
|
||||
return false;
|
||||
|
||||
return _surface.getPixel(x, y) != _keycolor;
|
||||
}
|
||||
|
||||
// Get the pixel at the point
|
||||
uint8 ShapeFrame::getPixel(int x, int y) const {
|
||||
// Add the offset
|
||||
x += _xoff;
|
||||
y += _yoff;
|
||||
|
||||
// First gross culling based on dims
|
||||
if (x < 0 || y < 0 || x >= _surface.w || y >= _surface.h)
|
||||
return _keycolor;
|
||||
|
||||
return _surface.getPixel(x, y);
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
66
engines/ultima/ultima8/gfx/shape_frame.h
Normal file
66
engines/ultima/ultima8/gfx/shape_frame.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_SHAPEFRAME_H
|
||||
#define ULTIMA8_GFX_SHAPEFRAME_H
|
||||
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RawShapeFrame;
|
||||
|
||||
/** A decompressed version of the RawShapeFrame for easier rendering */
|
||||
class ShapeFrame {
|
||||
public:
|
||||
|
||||
ShapeFrame(const RawShapeFrame *rawframe);
|
||||
~ShapeFrame();
|
||||
|
||||
int16 &_width;
|
||||
int16 &_height;
|
||||
int16 _xoff, _yoff;
|
||||
|
||||
uint8 _keycolor;
|
||||
|
||||
bool hasPoint(int x, int y) const; // Check to see if a point is in the frame
|
||||
|
||||
uint8 getPixel(int x, int y) const; // Get the pixel at the point
|
||||
|
||||
const Graphics::Surface &getSurface() const { return _surface; }
|
||||
|
||||
private:
|
||||
Graphics::Surface _surface;
|
||||
|
||||
/**
|
||||
* Load the pixel data from the raw shape rle data using key color for transparency
|
||||
* @param rawframe the raw shape to load rle data
|
||||
* @param keycolor the color representing transparency
|
||||
* @return false if the keycolor is found in the raw shape frame data
|
||||
*/
|
||||
bool load(const RawShapeFrame *rawframe, uint8 keycolor);
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
101
engines/ultima/ultima8/gfx/shape_info.cpp
Normal file
101
engines/ultima/ultima8/gfx/shape_info.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
/* 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 "ultima/ultima8/misc/common_types.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/shape_info.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
bool ShapeInfo::getTypeFlag(int typeFlag) const {
|
||||
if (GAME_IS_U8)
|
||||
return getTypeFlagU8(typeFlag);
|
||||
else if (GAME_IS_CRUSADER)
|
||||
return getTypeFlagCrusader(typeFlag);
|
||||
warning("Invalid game type for shape info");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeInfo::getTypeFlagU8(int typeFlag) const {
|
||||
// This is not nice. The Typeflags in U8 were stored in an 8 byte array
|
||||
// and they could access them with a number from 0 to 63
|
||||
// Problem: We don't store them in an 8 byte array so we can't access
|
||||
// with a number from 0 to 63
|
||||
|
||||
// So what we do is split the flag up into the bits
|
||||
|
||||
if (typeFlag <= 11) { // flags Byte 0, 1:0-3 Bits 0-11
|
||||
return (_flags >> typeFlag) & 1;
|
||||
} else if (typeFlag <= 15) { // family Byte 1:4-7 Bits 11-15
|
||||
return (_family >> (typeFlag - 12)) & 1;
|
||||
} else if (typeFlag <= 19) { // equipType Byte 2:0-3 Bits 16-19
|
||||
return (_equipType >> (typeFlag - 16)) & 1;
|
||||
} else if (typeFlag <= 23) { // x Byte 2:4-7 Bits 20-23
|
||||
return (_x >> (typeFlag - 20)) & 1;
|
||||
} else if (typeFlag <= 27) { // y Byte 3:0-3 Bits 24-27
|
||||
return (_y >> (typeFlag - 24)) & 1;
|
||||
} else if (typeFlag <= 31) { // z Byte 3:4-7 Bits 28-31
|
||||
return (_z >> (typeFlag - 28)) & 1;
|
||||
} else if (typeFlag <= 35) { // animtype Byte 4:0-3 Bits 32-35
|
||||
return (_animType >> (typeFlag - 32)) & 1;
|
||||
} else if (typeFlag <= 39) { // animdata Byte 4:4-7 Bits 36-49
|
||||
return (_animData >> (typeFlag - 36)) & 1;
|
||||
} else if (typeFlag <= 43) { // unknown Byte 5:0-3 Bits 40-43
|
||||
return (_animSpeed >> (typeFlag - 40)) & 1;
|
||||
} else if (typeFlag <= 47) { // _flags Byte 5:4-7 Bits 44-47
|
||||
return (_flags >> (12 + typeFlag - 44)) & 1;
|
||||
} else if (typeFlag <= 55) { // weight Byte 6 Bits 48-55
|
||||
return (_weight >> (typeFlag - 48)) & 1;
|
||||
} else if (typeFlag <= 63) { // volume Byte 7 Bits 56-63
|
||||
return (_volume >> (typeFlag - 56)) & 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShapeInfo::getTypeFlagCrusader(int typeFlag) const {
|
||||
if (typeFlag <= 11) { // _flags Byte 0, 1:0-3 Bits 0-11
|
||||
return (_flags >> typeFlag) & 1;
|
||||
} else if (typeFlag <= 16) { // _family Byte 1:4-7,2:0 Bits 12-16
|
||||
return (_family >> (typeFlag - 12)) & 1;
|
||||
} else if (typeFlag <= 20) { // unknown Byte 2:0-3 Bits 17-20
|
||||
warning("unknown typeFlag %d requested.", typeFlag);
|
||||
} else if (typeFlag <= 26) { // x Byte 2:4-7,3:0-1 Bits 21-26
|
||||
return (_x >> (typeFlag - 21)) & 1;
|
||||
} else if (typeFlag <= 31) { // y Byte 3:2-6 Bits 27-31
|
||||
return (_y >> (typeFlag - 27)) & 1;
|
||||
} else if (typeFlag <= 36) { // z Byte 3:7,4:0-3 Bits 32-36
|
||||
return (_z >> (typeFlag - 32)) & 1;
|
||||
} else if (typeFlag <= 47) {
|
||||
warning("unknown typeFlag %d requested.", typeFlag);
|
||||
} else if (typeFlag <= 55) { // _flags Byte 6: 0-7 Bits 48-55
|
||||
return (_flags >> (12 + typeFlag - 55)) & 1;
|
||||
} else if (typeFlag <= 71) {
|
||||
warning("unknown typeFlag %d requested.", typeFlag);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
199
engines/ultima/ultima8/gfx/shape_info.h
Normal file
199
engines/ultima/ultima8/gfx/shape_info.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_SHAPEINFO_H
|
||||
#define ULTIMA8_GFX_SHAPEINFO_H
|
||||
|
||||
#include "ultima/ultima8/world/weapon_info.h"
|
||||
#include "ultima/ultima8/world/armour_info.h"
|
||||
#include "ultima/ultima8/world/damage_info.h"
|
||||
#include "ultima/ultima8/world/actors/monster_info.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class ShapeInfo {
|
||||
public:
|
||||
enum SFlags {
|
||||
SI_FIXED = 0x0001,
|
||||
SI_SOLID = 0x0002,
|
||||
SI_SEA = 0x0004,
|
||||
SI_LAND = 0x0008,
|
||||
SI_OCCL = 0x0010,
|
||||
SI_BAG = 0x0020,
|
||||
SI_DAMAGING = 0x0040,
|
||||
SI_NOISY = 0x0080,
|
||||
SI_DRAW = 0x0100,
|
||||
SI_IGNORE = 0x0200,
|
||||
SI_ROOF = 0x0400, // reflective in Crusader?
|
||||
SI_TRANSL = 0x0800,
|
||||
SI_EDITOR = 0x1000,
|
||||
// Note: overlapping names for the rest of the bits depending on U8 or Cru.
|
||||
SI_U8_EXPLODE = 0x2000,
|
||||
SI_CRU_SELECTABLE = 0x2000,
|
||||
SI_UNKNOWN46 = 0x4000,
|
||||
SI_CRU_PRELOAD = 0x4000, // we don't need this flag, we preload everything.
|
||||
SI_UNKNOWN47 = 0x8000,
|
||||
SI_CRU_SOUND = 0x8000, // TODO: how is this used?
|
||||
SI_CRU_TARGETABLE = 0x10000,
|
||||
SI_CRU_NPC = 0x20000,
|
||||
SI_CRU_UNK66 = 0x40000,
|
||||
SI_CRU_UNK67 = 0x80000
|
||||
};
|
||||
|
||||
enum SFamily {
|
||||
SF_GENERIC = 0,
|
||||
SF_QUALITY = 1,
|
||||
SF_QUANTITY = 2,
|
||||
SF_GLOBEGG = 3,
|
||||
// "Unk" eggs are not "unknown", they are triggers for usecode
|
||||
// (unk is the source language for usecode)
|
||||
SF_UNKEGG = 4,
|
||||
SF_BREAKABLE = 5,
|
||||
SF_CONTAINER = 6,
|
||||
SF_MONSTEREGG = 7,
|
||||
SF_TELEPORTEGG = 8,
|
||||
SF_REAGENT = 9,
|
||||
SF_CRUWEAPON = 10, // Used in Crusader
|
||||
SF_CRUAMMO = 11, // Used in Crusader
|
||||
SF_CRUBOMB = 12, // Used in Crusader
|
||||
SF_CRUINVITEM = 13, // Used in Crusader
|
||||
SF_15 = 15
|
||||
};
|
||||
|
||||
enum SEquipType {
|
||||
SE_NONE = 0,
|
||||
SE_SHIELD = 1,
|
||||
SE_ARM = 2,
|
||||
SE_HEAD = 3,
|
||||
SE_BODY = 4,
|
||||
SE_LEGS = 5,
|
||||
SE_WEAPON = 6,
|
||||
SE_BACKPACK = 7
|
||||
};
|
||||
|
||||
uint32 _flags;
|
||||
uint32 _x, _y, _z;
|
||||
uint32 _family;
|
||||
uint32 _equipType;
|
||||
uint32 _animType, _animData, _animSpeed;
|
||||
uint32 _weight, _volume;
|
||||
|
||||
WeaponInfo *_weaponInfo;
|
||||
ArmourInfo *_armourInfo;
|
||||
MonsterInfo *_monsterInfo;
|
||||
DamageInfo *_damageInfo;
|
||||
|
||||
inline bool is_fixed() const {
|
||||
return (_flags & SI_FIXED) != 0;
|
||||
}
|
||||
inline bool is_solid() const {
|
||||
return (_flags & SI_SOLID) != 0;
|
||||
}
|
||||
inline bool is_sea() const {
|
||||
return (_flags & SI_SEA) != 0;
|
||||
}
|
||||
inline bool is_land() const {
|
||||
return (_flags & SI_LAND) != 0;
|
||||
}
|
||||
inline bool is_occl() const {
|
||||
return (_flags & SI_OCCL) != 0;
|
||||
}
|
||||
inline bool is_bag() const {
|
||||
return (_flags & SI_BAG) != 0;
|
||||
}
|
||||
inline bool is_damaging() const {
|
||||
return (_flags & SI_DAMAGING) != 0;
|
||||
}
|
||||
inline bool is_noisy() const {
|
||||
return (_flags & SI_NOISY) != 0;
|
||||
}
|
||||
inline bool is_draw() const {
|
||||
return (_flags & SI_DRAW) != 0;
|
||||
}
|
||||
inline bool is_ignore() const {
|
||||
return (_flags & SI_IGNORE) != 0;
|
||||
}
|
||||
inline bool is_roof() const {
|
||||
return (_flags & SI_ROOF) != 0;
|
||||
}
|
||||
inline bool is_translucent() const {
|
||||
return (_flags & SI_TRANSL) != 0;
|
||||
}
|
||||
inline bool is_editor() const {
|
||||
return (_flags & SI_EDITOR) != 0;
|
||||
}
|
||||
inline bool is_u8_explode() const {
|
||||
return (_flags & SI_U8_EXPLODE) != 0;
|
||||
}
|
||||
inline bool is_targetable() const {
|
||||
return (_flags & (SI_OCCL | SI_CRU_TARGETABLE));
|
||||
}
|
||||
inline bool is_invitem() const {
|
||||
return (_family == SF_CRUINVITEM);
|
||||
}
|
||||
|
||||
bool hasQuantity() const {
|
||||
return (_family == SF_QUANTITY || _family == SF_REAGENT);
|
||||
}
|
||||
|
||||
bool takesDamage() const {
|
||||
return (_damageInfo && _damageInfo->takesDamage());
|
||||
}
|
||||
|
||||
bool getTypeFlag(int typeFlag) const;
|
||||
bool getTypeFlagU8(int typeFlag) const;
|
||||
bool getTypeFlagCrusader(int typeFlag) const;
|
||||
|
||||
inline void getFootpadWorld(int32 &x, int32 &y, int32 &z, uint16 flipped) const;
|
||||
|
||||
ShapeInfo() :
|
||||
_flags(0), _x(0), _y(0), _z(0),
|
||||
_family(0), _equipType(0), _animType(0), _animData(0),
|
||||
_animSpeed(0), _weight(0), _volume(0),
|
||||
_weaponInfo(nullptr), _armourInfo(nullptr),
|
||||
_monsterInfo(nullptr), _damageInfo(nullptr) { }
|
||||
|
||||
~ShapeInfo() {
|
||||
delete _weaponInfo;
|
||||
delete[] _armourInfo;
|
||||
delete _monsterInfo;
|
||||
delete _damageInfo;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline void ShapeInfo::getFootpadWorld(int32 &x, int32 &y, int32 &z, uint16 flipped) const {
|
||||
z = _z * 8;
|
||||
|
||||
if (flipped) {
|
||||
x = _y * 32;
|
||||
y = _x * 32;
|
||||
} else {
|
||||
x = _x * 32;
|
||||
y = _y * 32;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
325
engines/ultima/ultima8/gfx/skf_player.cpp
Normal file
325
engines/ultima/ultima8/gfx/skf_player.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
/* 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 "ultima/ultima.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/misc/debugger.h"
|
||||
#include "ultima/ultima8/gfx/skf_player.h"
|
||||
#include "ultima/ultima8/convert/u8/convert_shape_u8.h"
|
||||
#include "ultima/ultima8/filesys/raw_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/gfx/texture.h"
|
||||
#include "ultima/ultima8/audio/music_process.h"
|
||||
#include "ultima/ultima8/audio/audio_process.h"
|
||||
#include "ultima/ultima8/audio/raw_audio_sample.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font.h"
|
||||
#include "ultima/ultima8/gfx/fonts/font_manager.h"
|
||||
#include "ultima/ultima8/gfx/fonts/rendered_text.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
enum SKFAction {
|
||||
SKF_PlayMusic = 3,
|
||||
SKF_SlowStopMusic = 4,
|
||||
SKF_PlaySFX = 5,
|
||||
SKF_StopSFX = 6,
|
||||
SKF_SetSpeed = 7,
|
||||
SKF_FadeOut = 8,
|
||||
SKF_FadeIn = 9,
|
||||
SKF_Wait = 12,
|
||||
SKF_PlaySound = 14,
|
||||
SKF_FadeWhite = 15,
|
||||
SKF_ClearSubs = 18
|
||||
};
|
||||
|
||||
struct SKFEvent {
|
||||
unsigned int _frame;
|
||||
SKFAction _action;
|
||||
unsigned int _data;
|
||||
};
|
||||
|
||||
// number of steps in a fade
|
||||
static const int FADESTEPS = 16; // HACK: half speed
|
||||
|
||||
|
||||
SKFPlayer::SKFPlayer(Common::SeekableReadStream *rs, int width, int height, bool introMusicHack)
|
||||
: _width(width), _height(height), _curFrame(0), _curObject(0), _curAction(0),
|
||||
_curEvent(0), _playing(false), _timer(0), _frameRate(15), _fadeColour(0),
|
||||
_fadeLevel(0), _buffer(nullptr), _subs(nullptr), _introMusicHack(introMusicHack),
|
||||
_lastUpdate(0), _subtitleY(0) {
|
||||
_skf = new RawArchive(rs);
|
||||
Common::ReadStream *eventlist = _skf->get_datasource(0);
|
||||
if (!eventlist) {
|
||||
warning("No eventlist found in SKF");
|
||||
return;
|
||||
}
|
||||
|
||||
parseEventList(eventlist);
|
||||
delete eventlist;
|
||||
|
||||
Graphics::Screen *screen = Ultima8Engine::get_instance()->getScreen();
|
||||
_buffer = new RenderSurface(_width, _height, screen->format);
|
||||
}
|
||||
|
||||
SKFPlayer::~SKFPlayer() {
|
||||
for (unsigned int i = 0; i < _events.size(); ++i)
|
||||
delete _events[i];
|
||||
|
||||
delete _skf;
|
||||
delete _buffer;
|
||||
delete _subs;
|
||||
}
|
||||
|
||||
void SKFPlayer::parseEventList(Common::ReadStream *eventlist) {
|
||||
uint16 frame = eventlist->readUint16LE();
|
||||
while (frame != 0xFFFF) {
|
||||
SKFEvent *ev = new SKFEvent;
|
||||
ev->_frame = frame;
|
||||
ev->_action = static_cast<SKFAction>(eventlist->readUint16LE());
|
||||
ev->_data = eventlist->readUint16LE();
|
||||
_events.push_back(ev);
|
||||
|
||||
frame = eventlist->readUint16LE();
|
||||
}
|
||||
}
|
||||
|
||||
void SKFPlayer::start() {
|
||||
uint32 color = TEX32_PACK_RGB(0, 0, 0);
|
||||
_buffer->fill32(color, 0, 0, _width, _height);
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc) musicproc->playMusic(0);
|
||||
_playing = true;
|
||||
_lastUpdate = g_system->getMillis();
|
||||
}
|
||||
|
||||
void SKFPlayer::stop() {
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
if (musicproc && !_introMusicHack) musicproc->playMusic(0);
|
||||
_playing = false;
|
||||
}
|
||||
|
||||
void SKFPlayer::paint(RenderSurface *surf, int /*lerp*/) {
|
||||
if (!_buffer) return;
|
||||
|
||||
if (!_fadeLevel) {
|
||||
Common::Rect srcRect(_width, _height);
|
||||
surf->Blit(*_buffer->getRawSurface(), srcRect, 0, 0);
|
||||
if (_subs)
|
||||
_subs->draw(surf, 60, _subtitleY);
|
||||
} else {
|
||||
uint32 fade = TEX32_PACK_RGBA(_fadeColour, _fadeColour, _fadeColour,
|
||||
(_fadeLevel * 255) / FADESTEPS);
|
||||
Common::Rect srcRect(_width, _height);
|
||||
surf->FadedBlit(*_buffer->getRawSurface(), srcRect, 0, 0, fade);
|
||||
if (_subs)
|
||||
_subs->drawBlended(surf, 60, _subtitleY, fade);
|
||||
}
|
||||
}
|
||||
|
||||
void SKFPlayer::run() {
|
||||
if (!_playing || !_buffer) return;
|
||||
|
||||
MusicProcess *musicproc = MusicProcess::get_instance();
|
||||
|
||||
// if doing something, continue
|
||||
if (_curAction) {
|
||||
if (_curAction == SKF_FadeOut || _curAction == SKF_FadeWhite) {
|
||||
_fadeLevel++;
|
||||
if (_fadeLevel == FADESTEPS) _curAction = 0; // done
|
||||
} else if (_curAction == SKF_FadeIn) {
|
||||
_fadeLevel--;
|
||||
if (_fadeLevel == 0) _curAction = 0; // done
|
||||
} else if (_curAction == SKF_SlowStopMusic) {
|
||||
if (!musicproc || !musicproc->isFading()) {
|
||||
if (musicproc)
|
||||
musicproc->playMusic(0); // stop playback
|
||||
_curAction = 0; // done
|
||||
} else {
|
||||
// continue to wait for fade to finish
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
debugC(kDebugVideo, "Unknown fade action: %u", _curAction);
|
||||
}
|
||||
}
|
||||
|
||||
// CHECKME: this timing may not be accurate enough...
|
||||
uint32 now = g_system->getMillis();
|
||||
if (_lastUpdate + (1000 / _frameRate) > now) return;
|
||||
|
||||
_lastUpdate += (1000 / _frameRate);
|
||||
|
||||
// if waiting, continue to wait
|
||||
if (_timer) {
|
||||
_timer--;
|
||||
return;
|
||||
}
|
||||
|
||||
Font *redfont;
|
||||
redfont = FontManager::get_instance()->getGameFont(6, true);
|
||||
|
||||
AudioProcess *audioproc = AudioProcess::get_instance();
|
||||
|
||||
bool subtitles = ConfMan.getBool("subtitles");
|
||||
bool speechMute = ConfMan.getBool("speech_mute");
|
||||
|
||||
// handle _events for the current frame
|
||||
while (_curEvent < _events.size() && _events[_curEvent]->_frame <= _curFrame) {
|
||||
debugCN(kDebugVideo, "Event %u: ", _curEvent);
|
||||
switch (_events[_curEvent]->_action) {
|
||||
case SKF_FadeOut:
|
||||
_curAction = SKF_FadeOut;
|
||||
_fadeColour = 0;
|
||||
_fadeLevel = 0;
|
||||
debugC(kDebugVideo, "FadeOut");
|
||||
break;
|
||||
case SKF_FadeIn:
|
||||
_curAction = SKF_FadeIn;
|
||||
_fadeLevel = FADESTEPS;
|
||||
debugC(kDebugVideo, "FadeIn");
|
||||
break;
|
||||
case SKF_FadeWhite:
|
||||
_curAction = SKF_FadeWhite;
|
||||
_fadeColour = 0xFF;
|
||||
_fadeLevel = 0;
|
||||
debugC(kDebugVideo, "FadeWhite");
|
||||
break;
|
||||
case SKF_Wait:
|
||||
debugC(kDebugVideo, "Wait %u", _events[_curEvent]->_data);
|
||||
_timer = _events[_curEvent]->_data;
|
||||
_curEvent++;
|
||||
return;
|
||||
case SKF_PlayMusic:
|
||||
debugC(kDebugVideo, "PlayMusic %u", _events[_curEvent]->_data);
|
||||
if (musicproc) musicproc->playMusic(_events[_curEvent]->_data);
|
||||
break;
|
||||
case SKF_SlowStopMusic:
|
||||
debugC(kDebugVideo, "SlowStopMusic");
|
||||
if (musicproc)
|
||||
musicproc->fadeMusic(1500);
|
||||
_curAction = SKF_SlowStopMusic;
|
||||
break;
|
||||
case SKF_PlaySFX:
|
||||
debugC(kDebugVideo, "PlaySFX %u", _events[_curEvent]->_data);
|
||||
if (audioproc) audioproc->playSFX(_events[_curEvent]->_data, 0x60, 0, 0);
|
||||
break;
|
||||
case SKF_StopSFX:
|
||||
debugC(kDebugVideo, "StopSFX %u", _events[_curEvent]->_data);
|
||||
if (audioproc) audioproc->stopSFX(_events[_curEvent]->_data, 0);
|
||||
break;
|
||||
case SKF_SetSpeed:
|
||||
debugC(kDebugVideo, "SetSpeed %u", _events[_curEvent]->_data);
|
||||
// _frameRate = _events[_curEvent]->_data;
|
||||
break;
|
||||
case SKF_PlaySound: {
|
||||
debugC(kDebugVideo, "PlaySound %u", _events[_curEvent]->_data);
|
||||
|
||||
if (!speechMute && audioproc) {
|
||||
uint8 *buf = _skf->get_object(_events[_curEvent]->_data);
|
||||
uint32 bufsize = _skf->get_size(_events[_curEvent]->_data);
|
||||
AudioSample *s;
|
||||
uint32 rate = buf[6] + (buf[7] << 8);
|
||||
bool stereo = (buf[8] == 2);
|
||||
s = new RawAudioSample(buf + 34, bufsize - 34,
|
||||
rate, true, stereo);
|
||||
audioproc->playSample(s, 0x60, 0, true);
|
||||
// FIXME: memory leak! (sample is never deleted)
|
||||
}
|
||||
|
||||
// subtitles
|
||||
char *textbuf = reinterpret_cast<char *>(
|
||||
_skf->get_object(_events[_curEvent]->_data - 1));
|
||||
uint32 textsize = _skf->get_size(_events[_curEvent]->_data - 1);
|
||||
if (subtitles && textsize > 7) {
|
||||
Std::string subtitle = (textbuf + 6);
|
||||
delete _subs;
|
||||
_subtitleY = textbuf[4] + (textbuf[5] << 8);
|
||||
unsigned int remaining;
|
||||
_subs = redfont->renderText(subtitle, remaining, 200, 0,
|
||||
Font::TEXT_CENTER);
|
||||
}
|
||||
delete textbuf;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case SKF_ClearSubs:
|
||||
debugC(kDebugVideo, "ClearSubs");
|
||||
delete _subs;
|
||||
_subs = nullptr;
|
||||
break;
|
||||
default:
|
||||
debugC(kDebugVideo, "Unknown action %d", _events[_curEvent]->_action);
|
||||
break;
|
||||
}
|
||||
|
||||
_curEvent++;
|
||||
}
|
||||
|
||||
_curFrame++;
|
||||
|
||||
uint16 objecttype = 0;
|
||||
do {
|
||||
_curObject++;
|
||||
if (_curObject >= _skf->getCount()) {
|
||||
stop(); // done
|
||||
return;
|
||||
}
|
||||
|
||||
// read object
|
||||
Common::SeekableReadStream * object = _skf->get_datasource(_curObject);
|
||||
if (!object)
|
||||
continue;
|
||||
|
||||
objecttype = object->size() > 2 ? object->readUint16LE() : 0;
|
||||
|
||||
debugC(kDebugVideo, "Object %u/%u, type = %u", _curObject, _skf->getCount(), objecttype);
|
||||
|
||||
switch (objecttype) {
|
||||
case 1:
|
||||
_palette.load(*object);
|
||||
_palette.updateNativeMap(_buffer->getRawSurface()->format);
|
||||
break;
|
||||
case 2: {
|
||||
object->seek(0);
|
||||
Shape *shape = new Shape(object, &U8SKFShapeFormat);
|
||||
shape->setPalette(&_palette);
|
||||
_buffer->BeginPainting();
|
||||
_buffer->Paint(shape, 0, 0, 0);
|
||||
_buffer->EndPainting();
|
||||
delete shape;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
delete object;
|
||||
} while (objecttype != 2);
|
||||
|
||||
_timer = 1; // HACK! timing is rather broken currently...
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
77
engines/ultima/ultima8/gfx/skf_player.h
Normal file
77
engines/ultima/ultima8/gfx/skf_player.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_SKFPLAYER_H
|
||||
#define ULTIMA8_GFX_SKFPLAYER_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/gfx/movie_player.h"
|
||||
#include "ultima/ultima8/gfx/render_surface.h"
|
||||
#include "ultima/ultima8/gfx/palette.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
struct SKFEvent;
|
||||
class RawArchive;
|
||||
class RenderedText;
|
||||
class Palette;
|
||||
|
||||
class SKFPlayer : public MoviePlayer {
|
||||
public:
|
||||
SKFPlayer(Common::SeekableReadStream *rs, int width, int height, bool introMusicHack = false);
|
||||
~SKFPlayer();
|
||||
|
||||
void run();
|
||||
void paint(RenderSurface *surf, int lerp);
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
bool isPlaying() const {
|
||||
return _playing;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void parseEventList(Common::ReadStream *rs);
|
||||
|
||||
int _width, _height;
|
||||
RawArchive *_skf;
|
||||
Std::vector<SKFEvent *> _events;
|
||||
unsigned int _curFrame, _curObject;
|
||||
unsigned int _curAction;
|
||||
unsigned int _curEvent;
|
||||
bool _playing;
|
||||
unsigned int _lastUpdate;
|
||||
unsigned int _timer;
|
||||
unsigned int _frameRate;
|
||||
uint8 _fadeColour, _fadeLevel;
|
||||
RenderSurface *_buffer;
|
||||
Palette _palette;
|
||||
RenderedText *_subs;
|
||||
int _subtitleY;
|
||||
bool _introMusicHack;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
58
engines/ultima/ultima8/gfx/texture.h
Normal file
58
engines/ultima/ultima8/gfx/texture.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_TEXTURE_H
|
||||
#define ULTIMA8_GFX_TEXTURE_H
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
//
|
||||
// Texturing Helper Macros
|
||||
//
|
||||
|
||||
// 32 Bit Texture bit operations
|
||||
#define TEX32_A_SHIFT 24
|
||||
#define TEX32_A_MASK 0xFF000000
|
||||
#define TEX32_A(col32) (((col32)&TEX32_A_MASK)>>TEX32_A_SHIFT)
|
||||
|
||||
#define TEX32_G_SHIFT 8
|
||||
#define TEX32_G_MASK 0x0000FF00
|
||||
#define TEX32_G(col32) (((col32)&TEX32_G_MASK)>>TEX32_G_SHIFT)
|
||||
|
||||
#define TEX32_B_SHIFT 16
|
||||
#define TEX32_B_MASK 0x00FF0000
|
||||
#define TEX32_B(col32) (((col32)&TEX32_B_MASK)>>TEX32_B_SHIFT)
|
||||
|
||||
#define TEX32_R_SHIFT 0
|
||||
#define TEX32_R_MASK 0x000000FF
|
||||
#define TEX32_R(col32) (((col32)&TEX32_R_MASK)>>TEX32_R_SHIFT)
|
||||
|
||||
#define TEX32_PACK_RGB(r, g, b) (uint32)(((0xFF) << TEX32_A_SHIFT) | ((r) << TEX32_R_SHIFT) | \
|
||||
((g) << TEX32_G_SHIFT) | ((b) << TEX32_B_SHIFT))
|
||||
|
||||
#define TEX32_PACK_RGBA(r, g, b, a) (uint32)(((a) << TEX32_A_SHIFT) | ((r) << TEX32_R_SHIFT) | \
|
||||
((g) << TEX32_G_SHIFT) | ((b) << TEX32_B_SHIFT))
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
472
engines/ultima/ultima8/gfx/type_flags.cpp
Normal file
472
engines/ultima/ultima8/gfx/type_flags.cpp
Normal file
@@ -0,0 +1,472 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/type_flags.h"
|
||||
#include "ultima/ultima8/conf/config_file_manager.h"
|
||||
#include "ultima/ultima8/ultima8.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/gfx/shape.h"
|
||||
#include "ultima/ultima8/games/treasure_loader.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
TypeFlags::TypeFlags() {
|
||||
}
|
||||
|
||||
|
||||
TypeFlags::~TypeFlags() {
|
||||
}
|
||||
|
||||
ShapeInfo *TypeFlags::getShapeInfo(uint32 shapenum) {
|
||||
if (shapenum < _shapeInfo.size())
|
||||
return &(_shapeInfo[shapenum]);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void TypeFlags::load(Common::SeekableReadStream *rs) {
|
||||
unsigned int blocksize = 8;
|
||||
if (GAME_IS_CRUSADER) {
|
||||
blocksize = 9;
|
||||
}
|
||||
|
||||
uint32 size = rs->size();
|
||||
uint32 count = size / blocksize;
|
||||
|
||||
_shapeInfo.clear();
|
||||
_shapeInfo.resize(count);
|
||||
|
||||
for (uint32 i = 0; i < count; ++i) {
|
||||
uint8 data[9];
|
||||
rs->read(data, blocksize);
|
||||
|
||||
ShapeInfo si;
|
||||
si._flags = 0;
|
||||
|
||||
if (GAME_IS_U8) {
|
||||
|
||||
if (data[0] & 0x01) si._flags |= ShapeInfo::SI_FIXED;
|
||||
if (data[0] & 0x02) si._flags |= ShapeInfo::SI_SOLID;
|
||||
if (data[0] & 0x04) si._flags |= ShapeInfo::SI_SEA;
|
||||
if (data[0] & 0x08) si._flags |= ShapeInfo::SI_LAND;
|
||||
if (data[0] & 0x10) si._flags |= ShapeInfo::SI_OCCL;
|
||||
if (data[0] & 0x20) si._flags |= ShapeInfo::SI_BAG;
|
||||
if (data[0] & 0x40) si._flags |= ShapeInfo::SI_DAMAGING;
|
||||
if (data[0] & 0x80) si._flags |= ShapeInfo::SI_NOISY;
|
||||
|
||||
if (data[1] & 0x01) si._flags |= ShapeInfo::SI_DRAW;
|
||||
if (data[1] & 0x02) si._flags |= ShapeInfo::SI_IGNORE;
|
||||
if (data[1] & 0x04) si._flags |= ShapeInfo::SI_ROOF;
|
||||
if (data[1] & 0x08) si._flags |= ShapeInfo::SI_TRANSL;
|
||||
si._family = data[1] >> 4;
|
||||
|
||||
si._equipType = data[2] & 0x0F;
|
||||
si._x = data[2] >> 4;
|
||||
|
||||
si._y = data[3] & 0x0F;
|
||||
si._z = data[3] >> 4;
|
||||
|
||||
si._animType = data[4] & 0x0F;
|
||||
si._animData = data[4] >> 4;
|
||||
si._animSpeed = data[5] & 0x0F;
|
||||
|
||||
if (data[5] & 0x10) si._flags |= ShapeInfo::SI_EDITOR;
|
||||
if (data[5] & 0x20) si._flags |= ShapeInfo::SI_U8_EXPLODE;
|
||||
if (data[5] & 0x40) si._flags |= ShapeInfo::SI_UNKNOWN46;
|
||||
if (data[5] & 0x80) si._flags |= ShapeInfo::SI_UNKNOWN47;
|
||||
|
||||
si._weight = data[6];
|
||||
si._volume = data[7];
|
||||
|
||||
} else if (GAME_IS_CRUSADER) {
|
||||
// Changes from U8 to Crusader:
|
||||
// * SI_OCCL seems to be used more like "target" in Cru
|
||||
// * SI_BAG bit seems to have a different meaning in Cru
|
||||
// (multi-panel?), but we don't use it anyway
|
||||
// * Family/x/y/z are all now 5 bits
|
||||
// * There are more and different flags in the last byte
|
||||
|
||||
if (data[0] & 0x01) si._flags |= ShapeInfo::SI_FIXED;
|
||||
if (data[0] & 0x02) si._flags |= ShapeInfo::SI_SOLID;
|
||||
if (data[0] & 0x04) si._flags |= ShapeInfo::SI_SEA;
|
||||
if (data[0] & 0x08) si._flags |= ShapeInfo::SI_LAND;
|
||||
if (data[0] & 0x10) si._flags |= ShapeInfo::SI_OCCL;
|
||||
if (data[0] & 0x20) si._flags |= ShapeInfo::SI_BAG;
|
||||
if (data[0] & 0x40) si._flags |= ShapeInfo::SI_DAMAGING;
|
||||
if (data[0] & 0x80) si._flags |= ShapeInfo::SI_NOISY;
|
||||
|
||||
if (data[1] & 0x01) si._flags |= ShapeInfo::SI_DRAW;
|
||||
if (data[1] & 0x02) si._flags |= ShapeInfo::SI_IGNORE;
|
||||
if (data[1] & 0x04) si._flags |= ShapeInfo::SI_ROOF;
|
||||
if (data[1] & 0x08) si._flags |= ShapeInfo::SI_TRANSL;
|
||||
si._family = data[1] >> 4;
|
||||
si._family += (data[2] & 1) << 4;
|
||||
|
||||
si._equipType = (data[2] >> 1) & 0xF;
|
||||
|
||||
si._x = ((data[3] << 3) | (data[2] >> 5)) & 0x1F;
|
||||
si._y = (data[3] >> 2) & 0x1F;
|
||||
si._z = ((data[4] << 1) | (data[3] >> 7)) & 0x1F;
|
||||
|
||||
si._animType = data[4] >> 4;
|
||||
si._animData = data[5] & 0x0F;
|
||||
si._animSpeed = data[5] >> 4;
|
||||
|
||||
if (si._animType != 0 && si._animSpeed == 0) {
|
||||
// avoid invalid speeds.
|
||||
warning("fixing anim speed 0 for shape %d", i);
|
||||
si._animSpeed = 1;
|
||||
}
|
||||
|
||||
if (data[6] & 0x01) si._flags |= ShapeInfo::SI_EDITOR;
|
||||
if (data[6] & 0x02) si._flags |= ShapeInfo::SI_CRU_SELECTABLE;
|
||||
if (data[6] & 0x04) si._flags |= ShapeInfo::SI_CRU_PRELOAD;
|
||||
if (data[6] & 0x08) si._flags |= ShapeInfo::SI_CRU_SOUND;
|
||||
if (data[6] & 0x10) si._flags |= ShapeInfo::SI_CRU_TARGETABLE;
|
||||
if (data[6] & 0x20) si._flags |= ShapeInfo::SI_CRU_NPC;
|
||||
if (data[6] & 0x40) si._flags |= ShapeInfo::SI_CRU_UNK66;
|
||||
if (data[6] & 0x80) si._flags |= ShapeInfo::SI_CRU_UNK67;
|
||||
|
||||
si._weight = data[7];
|
||||
si._volume = data[8];
|
||||
} else {
|
||||
error("unknown game type in type flags");
|
||||
}
|
||||
|
||||
si._weaponInfo = nullptr;
|
||||
si._armourInfo = nullptr;
|
||||
|
||||
_shapeInfo[i] = si;
|
||||
}
|
||||
|
||||
if (GAME_IS_U8) {
|
||||
// Workaround for incorrectly set solid flags on some "moss
|
||||
// curtains" in the catacombs. See also docs/u8bugs.txt
|
||||
for (uint32 i = 459; i <= 464; ++i) {
|
||||
_shapeInfo[i]._flags &= ~ShapeInfo::SI_SOLID;
|
||||
}
|
||||
}
|
||||
|
||||
loadWeaponInfo();
|
||||
loadArmourInfo();
|
||||
loadMonsterInfo();
|
||||
}
|
||||
|
||||
|
||||
// load weapon info from the 'weapons' config root
|
||||
void TypeFlags::loadWeaponInfo() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
|
||||
// load weapons
|
||||
Std::vector<Std::string> weaponkeys;
|
||||
Std::string category = "weapons";
|
||||
weaponkeys = config->listSections(category);
|
||||
for (const auto §ion : weaponkeys) {
|
||||
WeaponInfo *wi = new WeaponInfo;
|
||||
|
||||
int val = 0;
|
||||
|
||||
wi->_name = section;
|
||||
|
||||
config->get(category, section, "shape", val);
|
||||
wi->_shape = static_cast<uint32>(val);
|
||||
|
||||
config->get(category, section, "overlay", val);
|
||||
wi->_overlayType = static_cast<uint8>(val);
|
||||
|
||||
config->get(category, section, "overlay_shape", val);
|
||||
wi->_overlayShape = static_cast<uint32>(val);
|
||||
|
||||
config->get(category, section, "damage_mod", val);
|
||||
wi->_damageModifier = static_cast<uint8>(val);
|
||||
|
||||
config->get(category, section, "base_damage", val);
|
||||
wi->_baseDamage = static_cast<uint8>(val);
|
||||
|
||||
if (config->get(category, section, "attack_dex", val))
|
||||
wi->_dexAttackBonus = static_cast<uint8>(val);
|
||||
else
|
||||
wi->_dexAttackBonus = 0;
|
||||
|
||||
if (config->get(category, section, "defend_dex", val))
|
||||
wi->_dexDefendBonus = static_cast<uint8>(val);
|
||||
else
|
||||
wi->_dexDefendBonus = 0;
|
||||
|
||||
if (config->get(category, section, "armour", val))
|
||||
wi->_armourBonus = static_cast<uint8>(val);
|
||||
else
|
||||
wi->_armourBonus = 0;
|
||||
|
||||
config->get(category, section, "damage_type", val);
|
||||
wi->_damageType = static_cast<uint16>(val);
|
||||
|
||||
if (config->get(category, section, "treasure_chance", val))
|
||||
wi->_treasureChance = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_treasureChance = 0;
|
||||
|
||||
// Crusader-specific fields:
|
||||
|
||||
if (config->get(category, section, "ammo_type", val))
|
||||
wi->_ammoType = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_ammoType = 0;
|
||||
|
||||
if (config->get(category, section, "ammo_shape", val))
|
||||
wi->_ammoShape = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_ammoShape = 0;
|
||||
|
||||
if (config->get(category, section, "sound", val))
|
||||
wi->_sound = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_sound = 0;
|
||||
|
||||
if (config->get(category, section, "reload_sound", val))
|
||||
wi->_reloadSound = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_reloadSound = 0;
|
||||
|
||||
if (config->get(category, section, "display_frame", val))
|
||||
wi->_displayGumpFrame = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_displayGumpFrame = 0;
|
||||
|
||||
if (config->get(category, section, "display_shape", val))
|
||||
wi->_displayGumpShape = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_displayGumpShape = 3;
|
||||
|
||||
if (config->get(category, section, "small", val))
|
||||
wi->_small = static_cast<uint8>(val);
|
||||
else
|
||||
wi->_small = 0;
|
||||
|
||||
if (config->get(category, section, "clip_size", val))
|
||||
wi->_clipSize = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_clipSize = 10;
|
||||
|
||||
if (config->get(category, section, "energy", val))
|
||||
wi->_energyUse = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_energyUse = 0;
|
||||
|
||||
if (config->get(category, section, "shot_delay", val))
|
||||
wi->_shotDelay = static_cast<uint16>(val);
|
||||
else
|
||||
wi->_shotDelay = 0;
|
||||
|
||||
// TODO: this should be 1, 2, or 3 depending on weapon.
|
||||
// It's used in the AttackProcess
|
||||
wi->_field8 = 1;
|
||||
|
||||
if (wi->_shape > _shapeInfo.size()) {
|
||||
warning("ignoring weapon info for shape %d beyond size %d.",
|
||||
wi->_shape, _shapeInfo.size());
|
||||
delete wi;
|
||||
continue;
|
||||
}
|
||||
_shapeInfo[wi->_shape]._weaponInfo = wi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TypeFlags::loadArmourInfo() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
MainShapeArchive *msf = GameData::get_instance()->getMainShapes();
|
||||
|
||||
// load armour
|
||||
Std::vector<Std::string> armourkeys;
|
||||
Std::string category = "armour";
|
||||
armourkeys = config->listSections(category);
|
||||
for (const auto §ion : armourkeys) {
|
||||
ArmourInfo ai;
|
||||
|
||||
int val;
|
||||
|
||||
config->get(category, section, "shape", val);
|
||||
ai._shape = static_cast<uint32>(val);
|
||||
|
||||
assert(ai._shape < _shapeInfo.size());
|
||||
assert(msf->getShape(ai._shape));
|
||||
unsigned int framecount = msf->getShape(ai._shape)->frameCount();
|
||||
ArmourInfo *aia = _shapeInfo[ai._shape]._armourInfo;
|
||||
if (!aia) {
|
||||
aia = new ArmourInfo[framecount];
|
||||
_shapeInfo[ai._shape]._armourInfo = aia;
|
||||
for (unsigned int i = 0; i < framecount; ++i) {
|
||||
aia[i]._shape = 0;
|
||||
aia[i]._frame = 0;
|
||||
aia[i]._armourClass = 0;
|
||||
aia[i]._defenseType = 0;
|
||||
aia[i]._kickAttackBonus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
config->get(category, section, "frame", val);
|
||||
ai._frame = static_cast<uint32>(val);
|
||||
|
||||
assert(ai._frame < framecount);
|
||||
|
||||
config->get(category, section, "armour", val);
|
||||
ai._armourClass = static_cast<uint16>(val);
|
||||
|
||||
if (config->get(category, section, "type", val))
|
||||
ai._defenseType = static_cast<uint16>(val);
|
||||
else
|
||||
ai._defenseType = 0;
|
||||
|
||||
if (config->get(category, section, "kick_bonus", val))
|
||||
ai._kickAttackBonus = static_cast<uint16>(val);
|
||||
else
|
||||
ai._kickAttackBonus = 0;
|
||||
|
||||
aia[ai._frame] = ai;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeFlags::loadMonsterInfo() {
|
||||
ConfigFileManager *config = ConfigFileManager::get_instance();
|
||||
|
||||
TreasureLoader treasureLoader;
|
||||
treasureLoader.loadDefaults();
|
||||
|
||||
// load monsters
|
||||
Std::vector<Std::string> monsterkeys;
|
||||
Std::string category = "monsters";
|
||||
monsterkeys = config->listSections(category);
|
||||
for (const auto §ion : monsterkeys) {
|
||||
MonsterInfo *mi = new MonsterInfo;
|
||||
|
||||
int val;
|
||||
|
||||
config->get(category, section, "shape", val);
|
||||
mi->_shape = static_cast<uint32>(val);
|
||||
|
||||
config->get(category, section, "hp_min", val);
|
||||
mi->_minHp = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "hp_max", val);
|
||||
mi->_maxHp = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "dex_min", val);
|
||||
mi->_minDex = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "dex_max", val);
|
||||
mi->_maxDex = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "damage_min", val);
|
||||
mi->_minDmg = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "damage_max", val);
|
||||
mi->_maxDmg = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "armour", val);
|
||||
mi->_armourClass = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "alignment", val);
|
||||
mi->_alignment = static_cast<uint8>(val);
|
||||
|
||||
config->get(category, section, "unk", val);
|
||||
mi->_unk = (val != 0);
|
||||
|
||||
config->get(category, section, "damage_type", val);
|
||||
mi->_damageType = static_cast<uint16>(val);
|
||||
|
||||
config->get(category, section, "defense_type", val);
|
||||
mi->_defenseType = static_cast<uint16>(val);
|
||||
|
||||
if (config->get(category, section, "resurrection", val))
|
||||
mi->_resurrection = (val != 0);
|
||||
else
|
||||
mi->_resurrection = false;
|
||||
|
||||
if (config->get(category, section, "ranged", val))
|
||||
mi->_ranged = (val != 0);
|
||||
else
|
||||
mi->_ranged = false;
|
||||
|
||||
if (config->get(category, section, "shifter", val))
|
||||
mi->_shifter = (val != 0);
|
||||
else
|
||||
mi->_shifter = false;
|
||||
|
||||
if (config->get(category, section, "explode", val))
|
||||
mi->_explode = val;
|
||||
else
|
||||
mi->_explode = 0;
|
||||
|
||||
Std::string treasure;
|
||||
if (config->get(category, section, "treasure", treasure)) {
|
||||
bool ok = treasureLoader.parse(treasure, mi->_treasure);
|
||||
if (!ok) {
|
||||
warning("failed to parse treasure info for monster '%s;", section.c_str());
|
||||
mi->_treasure.clear();
|
||||
}
|
||||
} else {
|
||||
mi->_treasure.clear();
|
||||
}
|
||||
|
||||
assert(mi->_shape < _shapeInfo.size());
|
||||
_shapeInfo[mi->_shape]._monsterInfo = mi;
|
||||
}
|
||||
}
|
||||
|
||||
void TypeFlags::loadDamageDat(Common::SeekableReadStream *rs) {
|
||||
uint32 count = rs->size() / 6;
|
||||
if (_shapeInfo.size() < count) {
|
||||
warning("more damage info than shape info");
|
||||
return;
|
||||
}
|
||||
for (uint32 i = 0; i < count; i++) {
|
||||
byte damagedata[6];
|
||||
rs->read(damagedata, 6);
|
||||
if (damagedata[0] == 0)
|
||||
continue;
|
||||
|
||||
if (GAME_IS_REGRET && damagedata[0] == 1 && !damagedata[1] &&
|
||||
!damagedata[2] && !damagedata[3] &&
|
||||
!damagedata[4] && !damagedata[5]) {
|
||||
// WORKAROUND: No Regret has 3 shapes with this data pattern
|
||||
// which doesn't seem to be correct - eg, the elevator buttons
|
||||
// can be destroyed by gunshots which breaks the game.
|
||||
// Just ignore this pattern.
|
||||
// In No Remorse these maybe this pattern should be ignored too,
|
||||
// but there on some shapes that don't break the game.
|
||||
debug("Ignoring weird damage dat, shape %d (1 flag and rest 0s)", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
DamageInfo *di = new DamageInfo(damagedata);
|
||||
_shapeInfo[i]._damageInfo = di;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
51
engines/ultima/ultima8/gfx/type_flags.h
Normal file
51
engines/ultima/ultima8/gfx/type_flags.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_TYPEFLAGS_H
|
||||
#define ULTIMA8_GFX_TYPEFLAGS_H
|
||||
|
||||
#include "ultima/shared/std/containers.h"
|
||||
#include "ultima/ultima8/gfx/shape_info.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class TypeFlags {
|
||||
public:
|
||||
TypeFlags();
|
||||
~TypeFlags();
|
||||
|
||||
void load(Common::SeekableReadStream *rs);
|
||||
void loadDamageDat(Common::SeekableReadStream *rs);
|
||||
ShapeInfo *getShapeInfo(uint32 shape);
|
||||
|
||||
private:
|
||||
void loadWeaponInfo();
|
||||
void loadArmourInfo();
|
||||
void loadMonsterInfo();
|
||||
|
||||
Std::vector<ShapeInfo> _shapeInfo;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
104
engines/ultima/ultima8/gfx/wpn_ovlay_dat.cpp
Normal file
104
engines/ultima/ultima8/gfx/wpn_ovlay_dat.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/* 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 "ultima/ultima8/misc/debugger.h"
|
||||
|
||||
#include "ultima/ultima8/gfx/wpn_ovlay_dat.h"
|
||||
|
||||
#include "ultima/ultima8/world/actors/weapon_overlay.h"
|
||||
#include "ultima/ultima8/filesys/raw_archive.h"
|
||||
#include "ultima/ultima8/games/game_data.h"
|
||||
#include "ultima/ultima8/gfx/main_shape_archive.h"
|
||||
#include "ultima/ultima8/world/actors/anim_action.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
WpnOvlayDat::WpnOvlayDat() {
|
||||
}
|
||||
|
||||
WpnOvlayDat::~WpnOvlayDat() {
|
||||
for (unsigned int i = 0; i < _overlay.size(); i++)
|
||||
delete _overlay[i];
|
||||
}
|
||||
|
||||
const WeaponOverlayFrame *WpnOvlayDat::getOverlayFrame(uint32 action, int type,
|
||||
Direction direction,
|
||||
int frame) const {
|
||||
if (action >= _overlay.size())
|
||||
return nullptr;
|
||||
if (!_overlay[action])
|
||||
return nullptr;
|
||||
return _overlay[action]->getFrame(type, direction, frame);
|
||||
}
|
||||
|
||||
|
||||
void WpnOvlayDat::load(RawArchive *overlaydat) {
|
||||
MainShapeArchive *msf = GameData::get_instance()->getMainShapes();
|
||||
assert(msf);
|
||||
|
||||
_overlay.resize(overlaydat->getCount());
|
||||
|
||||
for (unsigned int action = 0; action < _overlay.size(); action++) {
|
||||
Common::SeekableReadStream *rs = overlaydat->get_datasource(action);
|
||||
_overlay[action] = nullptr;
|
||||
|
||||
if (rs && rs->size()) {
|
||||
// get Avatar's animation
|
||||
const AnimAction *anim = msf->getAnim(1, action);
|
||||
if (!anim) {
|
||||
warning("Skipping wpnovlay action %u because avatar animation doesn't exist.", action);
|
||||
continue;
|
||||
}
|
||||
|
||||
AnimWeaponOverlay *awo = new AnimWeaponOverlay;
|
||||
_overlay[action] = awo;
|
||||
|
||||
unsigned int animlength = anim->getSize();
|
||||
unsigned int dircount = anim->getDirCount();
|
||||
|
||||
unsigned int typecount = rs->size() / (4 * dircount * animlength);
|
||||
awo->_overlay.resize(typecount);
|
||||
|
||||
for (unsigned int type = 0; type < typecount; type++) {
|
||||
awo->_overlay[type]._dirCount = dircount;
|
||||
awo->_overlay[type]._frames =
|
||||
new Std::vector<WeaponOverlayFrame>[dircount];
|
||||
for (unsigned int dir = 0; dir < dircount; dir++) {
|
||||
awo->_overlay[type]._frames[dir].resize(animlength);
|
||||
for (unsigned int frame = 0; frame < animlength; frame++) {
|
||||
WeaponOverlayFrame f;
|
||||
f._xOff = rs->readSByte();
|
||||
f._yOff = rs->readSByte();
|
||||
f._frame = rs->readUint16LE();
|
||||
|
||||
awo->_overlay[type]._frames[dir][frame] = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete rs;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
53
engines/ultima/ultima8/gfx/wpn_ovlay_dat.h
Normal file
53
engines/ultima/ultima8/gfx/wpn_ovlay_dat.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_WPNOVLAYDAT_H
|
||||
#define ULTIMA8_GFX_WPNOVLAYDAT_H
|
||||
|
||||
#include "ultima/ultima8/misc/direction.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
class RawArchive;
|
||||
struct AnimWeaponOverlay;
|
||||
struct WeaponOverlayFrame;
|
||||
|
||||
class WpnOvlayDat {
|
||||
public:
|
||||
WpnOvlayDat();
|
||||
~WpnOvlayDat();
|
||||
|
||||
//! load weapon overlay data from wpnovlay.dat
|
||||
//! NB: anim.dat must have already been read
|
||||
void load(RawArchive *overlaydat);
|
||||
|
||||
const WeaponOverlayFrame *getOverlayFrame(uint32 action, int type,
|
||||
Direction direction, int frame) const;
|
||||
|
||||
private:
|
||||
Std::vector<AnimWeaponOverlay *> _overlay;
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
67
engines/ultima/ultima8/gfx/xform_blend.cpp
Normal file
67
engines/ultima/ultima8/gfx/xform_blend.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* 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 "ultima/ultima8/gfx/xform_blend.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
const uint8 U8XFormPal[1024] = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
48, 48, 48, 80, // (green->dark grey)
|
||||
24, 24, 24, 128, // (*->vdark grey)
|
||||
64, 64, 24, 64, // (yellow)
|
||||
80, 80, 80, 80, // (white->grey)
|
||||
180, 90, 0, 80, // (red->orange)
|
||||
0, 0, 252, 40, // (blue)
|
||||
0, 0, 104, 40, // (blue)
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
// TODO: Only eyeballed these, should try and make it more exact to original.
|
||||
const uint8 CruXFormPal[1024] = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
48, 48, 48, 80, // (green->dark grey)
|
||||
24, 24, 24, 128, // (*->vdark grey)
|
||||
64, 64, 24, 64, // (yellow)
|
||||
80, 80, 80, 80,
|
||||
48, 48, 48, 140, // (*->grey)
|
||||
24, 24, 24, 140, // (*->dark grey) 13
|
||||
10, 10, 10, 140, // (*->vdark grey) 14
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
36
engines/ultima/ultima8/gfx/xform_blend.h
Normal file
36
engines/ultima/ultima8/gfx/xform_blend.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ULTIMA8_GFX_XFORMBLEND_H
|
||||
#define ULTIMA8_GFX_XFORMBLEND_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Ultima8 {
|
||||
|
||||
extern const uint8 U8XFormPal[1024];
|
||||
extern const uint8 CruXFormPal[1024];
|
||||
|
||||
} // End of namespace Ultima8
|
||||
} // End of namespace Ultima
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user