- 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:
Nicola Mettifogo 2007-08-06 22:03:17 +00:00
parent c60fc2202f
commit 797f114aac
7 changed files with 90 additions and 59 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -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 {