- Renamed BitBuffer to MaskBuffer
- Added PathBuffer to handle 1-bit buffers for walkable areas - Changed relevant walk code to use PathBuffer objects for querying screen dimensions. svn-id: r28478
This commit is contained in:
parent
c60fc2202f
commit
797f114aac
7 changed files with 90 additions and 59 deletions
|
@ -592,20 +592,19 @@ void DosDisk_ns::loadBackground(const char *filename) {
|
|||
Graphics::Surface *bg = new Graphics::Surface;
|
||||
bg->create(_vm->_screenWidth, _vm->_screenHeight, 1);
|
||||
|
||||
BitBuffer *mask = new BitBuffer;
|
||||
MaskBuffer *mask = new MaskBuffer;
|
||||
mask->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
byte *path = (byte*)calloc(1, _vm->_screenPathSize);
|
||||
|
||||
PathBuffer *path = new PathBuffer;
|
||||
path->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
|
||||
Graphics::PackBitsReadStream stream(_resArchive);
|
||||
unpackBackground(&stream, (byte*)bg->pixels, mask->data, path);
|
||||
unpackBackground(&stream, (byte*)bg->pixels, mask->data, path->data);
|
||||
|
||||
_vm->_gfx->setBackground(bg);
|
||||
_vm->_gfx->setMask(mask);
|
||||
_vm->setPath(path);
|
||||
|
||||
free(path);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -622,13 +621,15 @@ void DosDisk_ns::loadMaskAndPath(const char *name) {
|
|||
if (!_resArchive.openArchivedFile(path))
|
||||
errorFileNotFound(name);
|
||||
|
||||
BitBuffer *mask = new BitBuffer;
|
||||
MaskBuffer *mask = new MaskBuffer;
|
||||
mask->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
byte *pathBuf = (byte*)calloc(1, _vm->_screenPathSize);
|
||||
|
||||
PathBuffer *pathBuf = new PathBuffer;
|
||||
pathBuf->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
|
||||
parseDepths(_resArchive);
|
||||
|
||||
_resArchive.read(pathBuf, _vm->_screenPathSize);
|
||||
_resArchive.read(pathBuf->data, pathBuf->size);
|
||||
_resArchive.read(mask->data, mask->size);
|
||||
|
||||
_vm->_gfx->setMask(mask);
|
||||
|
@ -1238,7 +1239,7 @@ void AmigaDisk_ns::loadMask(const char *name) {
|
|||
s->seek(0x126, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
|
||||
Graphics::PackBitsReadStream stream(*s);
|
||||
|
||||
BitBuffer *mask = new BitBuffer;
|
||||
MaskBuffer *mask = new MaskBuffer;
|
||||
mask->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
stream.read(mask->data, mask->size);
|
||||
buildMask(mask->data);
|
||||
|
@ -1262,10 +1263,12 @@ void AmigaDisk_ns::loadPath(const char *name) {
|
|||
s->seek(0x120, SEEK_SET); // HACK: skipping IFF/ILBM header should be done by analysis, not magic
|
||||
|
||||
Graphics::PackBitsReadStream stream(*s);
|
||||
byte *buf = (byte*)malloc(_vm->_screenPathSize);
|
||||
stream.read(buf, _vm->_screenPathSize);
|
||||
|
||||
PathBuffer *buf = new PathBuffer;
|
||||
buf->create(_vm->_screenWidth, _vm->_screenHeight);
|
||||
stream.read(buf->data, buf->size);
|
||||
_vm->setPath(buf);
|
||||
free(buf);
|
||||
|
||||
delete s;
|
||||
|
||||
return;
|
||||
|
|
|
@ -760,7 +760,7 @@ void Gfx::setBackground(Graphics::Surface *surface) {
|
|||
copyScreen(kBit2, kBitBack);
|
||||
}
|
||||
|
||||
void Gfx::setMask(BitBuffer *buffer) {
|
||||
void Gfx::setMask(MaskBuffer *buffer) {
|
||||
if (_depthMask)
|
||||
delete _depthMask;
|
||||
|
||||
|
|
|
@ -146,12 +146,9 @@ enum Fonts {
|
|||
kFontMenu = 2
|
||||
};
|
||||
|
||||
struct BitBuffer {
|
||||
struct MaskBuffer {
|
||||
// handles a 2-bit depth buffer used for z-buffering
|
||||
|
||||
// TODO: generalize to handle 1-bit buffers, so that
|
||||
// path buffers can be handled as well (use templates?)
|
||||
|
||||
uint16 w;
|
||||
uint16 internalWidth;
|
||||
uint16 h;
|
||||
|
@ -159,10 +156,10 @@ struct BitBuffer {
|
|||
byte *data;
|
||||
|
||||
public:
|
||||
BitBuffer() : w(0), internalWidth(0), h(0), data(0) {
|
||||
MaskBuffer() : w(0), internalWidth(0), h(0), data(0) {
|
||||
}
|
||||
|
||||
~BitBuffer() {
|
||||
~MaskBuffer() {
|
||||
free();
|
||||
}
|
||||
|
||||
|
@ -220,7 +217,7 @@ public:
|
|||
|
||||
// location
|
||||
void setBackground(Graphics::Surface *surf);
|
||||
void setMask(BitBuffer *buffer);
|
||||
void setMask(MaskBuffer *buffer);
|
||||
int16 queryMask(int16 v);
|
||||
void intGrottaHackMask();
|
||||
void restoreBackground(const Common::Rect& r);
|
||||
|
@ -274,7 +271,7 @@ public:
|
|||
protected:
|
||||
Parallaction* _vm;
|
||||
Graphics::Surface *_buffers[NUM_BUFFERS];
|
||||
BitBuffer *_depthMask;
|
||||
MaskBuffer *_depthMask;
|
||||
static byte _mouseArrow[256];
|
||||
StaticCnv *_mouseComposedArrow;
|
||||
Font *_font;
|
||||
|
@ -295,3 +292,4 @@ protected:
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -131,6 +131,9 @@ Parallaction::~Parallaction() {
|
|||
delete _zoneTypeNames;
|
||||
delete _zoneFlagNames;
|
||||
|
||||
if (_pathBuffer)
|
||||
delete _pathBuffer;
|
||||
|
||||
_animations.remove(&_char._ani);
|
||||
|
||||
freeLocation();
|
||||
|
@ -173,7 +176,8 @@ int Parallaction::init() {
|
|||
|
||||
memset(_locationNames, 0, 120*32);
|
||||
|
||||
initWalk(); // needs to be pushed into subclass
|
||||
_pathBuffer = 0;
|
||||
|
||||
initInventory(); // needs to be pushed into subclass
|
||||
|
||||
_animations.push_front(&_char._ani);
|
||||
|
|
|
@ -315,7 +315,7 @@ public:
|
|||
void resumeJobs();
|
||||
void runJobs();
|
||||
|
||||
void setPath(byte *path);
|
||||
void setPath(PathBuffer *buffer);
|
||||
void finalizeWalk(WalkNodeList *list);
|
||||
int16 selectWalkFrame(const Common::Point& pos, const WalkNode* from);
|
||||
void clipMove(Common::Point& pos, const WalkNode* from);
|
||||
|
@ -361,6 +361,7 @@ public:
|
|||
|
||||
int32 _screenPathWidth;
|
||||
int32 _screenPathSize;
|
||||
PathBuffer *_pathBuffer;
|
||||
|
||||
SoundMan *_soundMan;
|
||||
|
||||
|
@ -451,7 +452,6 @@ protected: // members
|
|||
void displayItemComment(ExamineData *data);
|
||||
|
||||
void parseWalkNodes(Script& script, WalkNodeList &list);
|
||||
void initWalk();
|
||||
uint16 checkDoor();
|
||||
|
||||
Animation * parseAnimation(Script &script, AnimationList &list, char *name);
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
namespace Parallaction {
|
||||
|
||||
static byte *_buffer;
|
||||
|
||||
static uint16 _doorData1 = 1000;
|
||||
static Zone *_zoneTrap = NULL;
|
||||
|
||||
|
@ -38,32 +36,27 @@ static uint16 walkData1 = 0;
|
|||
static uint16 walkData2 = 0; // next walk frame
|
||||
|
||||
|
||||
uint16 queryPath(uint16 x, uint16 y) {
|
||||
|
||||
// NOTE: a better solution would have us mirror each byte in the mask in the loading routine
|
||||
// AmigaDisk_ns::loadPath() instead of doing it here.
|
||||
|
||||
byte _al = _buffer[y*40 + x/8];
|
||||
byte _dl = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
|
||||
|
||||
return _al & (1 << _dl);
|
||||
inline byte PathBuffer::getValue(uint16 x, uint16 y) {
|
||||
byte m = data[(x >> 3) + y * internalWidth];
|
||||
uint n = (_vm->getPlatform() == Common::kPlatformPC) ? (x & 7) : (7 - (x & 7));
|
||||
return ((1 << n) & m) >> n;
|
||||
}
|
||||
|
||||
// adjusts position towards nearest walkable point
|
||||
//
|
||||
void PathBuilder::correctPathPoint(Common::Point &to) {
|
||||
|
||||
if (queryPath(to.x, to.y)) return;
|
||||
if (_vm->_pathBuffer->getValue(to.x, to.y)) return;
|
||||
|
||||
int16 right = to.x;
|
||||
int16 left = to.x;
|
||||
do {
|
||||
right++;
|
||||
} while ((queryPath(right, to.y) == 0) && (right < _vm->_screenWidth));
|
||||
} while ((_vm->_pathBuffer->getValue(right, to.y) == 0) && (right < _vm->_pathBuffer->w));
|
||||
do {
|
||||
left--;
|
||||
} while ((queryPath(left, to.y) == 0) && (left > 0));
|
||||
right = (right == _vm->_screenWidth) ? 1000 : right - to.x;
|
||||
} while ((_vm->_pathBuffer->getValue(left, to.y) == 0) && (left > 0));
|
||||
right = (right == _vm->_pathBuffer->w) ? 1000 : right - to.x;
|
||||
left = (left == 0) ? 1000 : to.x - left;
|
||||
|
||||
|
||||
|
@ -71,12 +64,12 @@ void PathBuilder::correctPathPoint(Common::Point &to) {
|
|||
int16 bottom = to.y;
|
||||
do {
|
||||
top--;
|
||||
} while ((queryPath(to.x, top) == 0) && (top > 0));
|
||||
} while ((_vm->_pathBuffer->getValue(to.x, top) == 0) && (top > 0));
|
||||
do {
|
||||
bottom++;
|
||||
} while ((queryPath(to.x, bottom) == 0) && (bottom < _vm->_screenHeight));
|
||||
} while ((_vm->_pathBuffer->getValue(to.x, bottom) == 0) && (bottom < _vm->_pathBuffer->h));
|
||||
top = (top == 0) ? 1000 : to.y - top;
|
||||
bottom = (bottom == _vm->_screenHeight) ? 1000 : bottom - to.y;
|
||||
bottom = (bottom == _vm->_pathBuffer->h) ? 1000 : bottom - to.y;
|
||||
|
||||
|
||||
int16 closeX = (right >= left) ? left : right;
|
||||
|
@ -232,10 +225,10 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
|
|||
|
||||
while (foot != arg) {
|
||||
|
||||
if (foot.x < x && queryPath(foot.x + 1, foot.y) != 0) foot.x++;
|
||||
if (foot.x > x && queryPath(foot.x - 1, foot.y) != 0) foot.x--;
|
||||
if (foot.y < y && queryPath(foot.x, foot.y + 1) != 0) foot.y++;
|
||||
if (foot.y > y && queryPath(foot.x, foot.y - 1) != 0) foot.y--;
|
||||
if (foot.x < x && _vm->_pathBuffer->getValue(foot.x + 1, foot.y) != 0) foot.x++;
|
||||
if (foot.x > x && _vm->_pathBuffer->getValue(foot.x - 1, foot.y) != 0) foot.x--;
|
||||
if (foot.y < y && _vm->_pathBuffer->getValue(foot.x, foot.y + 1) != 0) foot.y++;
|
||||
if (foot.y > y && _vm->_pathBuffer->getValue(foot.x, foot.y - 1) != 0) foot.y--;
|
||||
|
||||
|
||||
if (foot == v8 && foot != arg) {
|
||||
|
@ -245,10 +238,10 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
|
|||
|
||||
while (foot != arg) {
|
||||
|
||||
if (foot.x < x && queryPath(foot.x + 1, foot.y) == 0) foot.x++;
|
||||
if (foot.x > x && queryPath(foot.x - 1, foot.y) == 0) foot.x--;
|
||||
if (foot.y < y && queryPath(foot.x, foot.y + 1) == 0) foot.y++;
|
||||
if (foot.y > y && queryPath(foot.x, foot.y - 1) == 0) foot.y--;
|
||||
if (foot.x < x && _vm->_pathBuffer->getValue(foot.x + 1, foot.y) == 0) foot.x++;
|
||||
if (foot.x > x && _vm->_pathBuffer->getValue(foot.x - 1, foot.y) == 0) foot.x--;
|
||||
if (foot.y < y && _vm->_pathBuffer->getValue(foot.x, foot.y + 1) == 0) foot.y++;
|
||||
if (foot.y > y && _vm->_pathBuffer->getValue(foot.x, foot.y - 1) == 0) foot.y--;
|
||||
|
||||
if (foot == v8 && foot != arg)
|
||||
return 0;
|
||||
|
@ -272,19 +265,19 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNode *Node) {
|
|||
|
||||
void Parallaction::clipMove(Common::Point& pos, const WalkNode* from) {
|
||||
|
||||
if ((pos.x < from->_x) && (pos.x < _screenWidth) && (queryPath(_char._ani.width()/2 + pos.x + 2, _char._ani.height() + pos.y) != 0)) {
|
||||
if ((pos.x < from->_x) && (pos.x < _vm->_pathBuffer->w) && (_pathBuffer->getValue(_char._ani.width()/2 + pos.x + 2, _char._ani.height() + pos.y) != 0)) {
|
||||
pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x;
|
||||
}
|
||||
|
||||
if ((pos.x > from->_x) && (pos.x > -20) && (queryPath(_char._ani.width()/2 + pos.x - 2, _char._ani.height() + pos.y) != 0)) {
|
||||
if ((pos.x > from->_x) && (pos.x > -20) && (_pathBuffer->getValue(_char._ani.width()/2 + pos.x - 2, _char._ani.height() + pos.y) != 0)) {
|
||||
pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x;
|
||||
}
|
||||
|
||||
if ((pos.y < from->_y) && (pos.y < (_screenHeight - _char._ani.height())) && (queryPath(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y + 2) != 0)) {
|
||||
if ((pos.y < from->_y) && (pos.y < (_vm->_pathBuffer->h - _char._ani.height())) && (_pathBuffer->getValue(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y + 2) != 0)) {
|
||||
pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y;
|
||||
}
|
||||
|
||||
if ((pos.y > from->_y) && (pos.y > -20) && (queryPath(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y- 2) != 0)) {
|
||||
if ((pos.y > from->_y) && (pos.y > -20) && (_pathBuffer->getValue(_char._ani.width()/2 + pos.x, _char._ani.height() + pos.y- 2) != 0)) {
|
||||
pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y;
|
||||
}
|
||||
|
||||
|
@ -428,12 +421,11 @@ void jobWalk(void *parm, Job *j) {
|
|||
}
|
||||
|
||||
|
||||
void Parallaction::setPath(byte *path) {
|
||||
memcpy(_buffer, path, _screenPathSize);
|
||||
}
|
||||
void Parallaction::setPath(PathBuffer *buffer) {
|
||||
if (_pathBuffer)
|
||||
delete _pathBuffer;
|
||||
|
||||
void Parallaction::initWalk() {
|
||||
_buffer = (byte*)malloc(_screenPathSize);
|
||||
_pathBuffer = buffer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -459,3 +451,4 @@ PathBuilder::PathBuilder(Animation *anim) : _anim(anim), _list(0) {
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,39 @@ typedef ManagedList<WalkNode*> WalkNodeList;
|
|||
|
||||
void jobWalk(void*, Job *j);
|
||||
|
||||
struct PathBuffer {
|
||||
// handles a 1-bit depth buffer used for masking non-walkable areas
|
||||
|
||||
uint16 w;
|
||||
uint16 internalWidth;
|
||||
uint16 h;
|
||||
uint size;
|
||||
byte *data;
|
||||
|
||||
public:
|
||||
PathBuffer() : w(0), internalWidth(0), h(0), data(0) {
|
||||
}
|
||||
|
||||
~PathBuffer() {
|
||||
free();
|
||||
}
|
||||
|
||||
void create(uint16 width, uint16 height) {
|
||||
w = width;
|
||||
internalWidth = w >> 3;
|
||||
h = height;
|
||||
size = (internalWidth * h);
|
||||
data = (byte*)calloc(size, 1);
|
||||
}
|
||||
|
||||
void free() {
|
||||
if (data)
|
||||
::free(data);
|
||||
}
|
||||
|
||||
inline byte getValue(uint16 x, uint16 y);
|
||||
};
|
||||
|
||||
|
||||
class PathBuilder {
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue