Changing the Urban Runner sprite drawer to work more correctly. It does use YUV data, but I can use the ditherer there
svn-id: r35308
This commit is contained in:
parent
443158fd89
commit
c65886a3ea
8 changed files with 167 additions and 44 deletions
|
@ -755,18 +755,29 @@ void Draw_v2::spriteOperation(int16 operation) {
|
|||
|
||||
case DRAW_LOADSPRITE:
|
||||
id = _spriteLeft;
|
||||
if (id >= 30000) {
|
||||
dataBuf =
|
||||
_vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom);
|
||||
|
||||
if ((id >= 30000) || (_vm->_game->_lomHandle >= 0)) {
|
||||
dataBuf = 0;
|
||||
|
||||
if (_vm->_game->_lomHandle >= 0)
|
||||
warning("Urban Stub: LOADSPRITE %d, LOM", id);
|
||||
else
|
||||
dataBuf = _vm->_game->loadExtData(id, &_spriteRight, &_spriteBottom);
|
||||
|
||||
if (!dataBuf)
|
||||
break;
|
||||
|
||||
_vm->_video->drawPackedSprite(dataBuf,
|
||||
_spriteRight, _spriteBottom, _destSpriteX, _destSpriteY,
|
||||
_transparency, _spritesArray[_destSurface]);
|
||||
|
||||
dirtiedRect(_destSurface, _destSpriteX, _destSpriteY,
|
||||
_destSpriteX + _spriteRight - 1, _destSpriteY + _spriteBottom - 1);
|
||||
|
||||
delete[] dataBuf;
|
||||
break;
|
||||
}
|
||||
|
||||
// Load from .TOT resources
|
||||
itemPtr = &_vm->_game->_totResourceTable->items[id];
|
||||
offset = itemPtr->offset;
|
||||
|
|
|
@ -45,6 +45,7 @@ Game::Game(GobEngine *vm) : _vm(vm) {
|
|||
_totResourceTable = 0;
|
||||
_imFileData = 0;
|
||||
_extHandle = 0;
|
||||
_lomHandle = -1;
|
||||
_collisionAreas = 0;
|
||||
_shouldPushColls = 0;
|
||||
|
||||
|
@ -393,12 +394,33 @@ int32 Game::loadTotFile(const char *path) {
|
|||
int16 handle;
|
||||
int32 size;
|
||||
|
||||
_lomHandle = -1;
|
||||
|
||||
size = -1;
|
||||
handle = _vm->_dataIO->openData(path);
|
||||
if (handle >= 0) {
|
||||
_vm->_dataIO->closeData(handle);
|
||||
size = _vm->_dataIO->getDataSize(path);
|
||||
_totFileData = _vm->_dataIO->getData(path);
|
||||
|
||||
if (!scumm_stricmp(path + strlen(path) - 3, "LOM")) {
|
||||
warning("Urban Stub: loadTotFile %s", path);
|
||||
|
||||
_lomHandle = handle;
|
||||
|
||||
DataStream *stream = _vm->_dataIO->openAsStream(handle);
|
||||
|
||||
stream->seek(48);
|
||||
size = stream->readUint32LE();
|
||||
stream->seek(0);
|
||||
|
||||
_totFileData = new byte[size];
|
||||
stream->read(_totFileData, size);
|
||||
|
||||
delete stream;
|
||||
} else {
|
||||
_vm->_dataIO->closeData(handle);
|
||||
size = _vm->_dataIO->getDataSize(path);
|
||||
_totFileData = _vm->_dataIO->getData(path);
|
||||
}
|
||||
|
||||
} else {
|
||||
Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path);
|
||||
|
||||
|
|
|
@ -116,6 +116,7 @@ public:
|
|||
byte *_totFileData;
|
||||
|
||||
int16 _extHandle;
|
||||
int16 _lomHandle;
|
||||
|
||||
char _totToLoad[20];
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ void PaletteLUT::buildNext() {
|
|||
void PaletteLUT::build(int d1) {
|
||||
byte *lut = _lut + d1 * _dim2;
|
||||
|
||||
warning("LUT %d/%d", d1, _dim1 - 1);
|
||||
// warning("LUT %d/%d", d1, _dim1 - 1);
|
||||
|
||||
for (int j = 0; j < _dim1; j++) {
|
||||
for (int k = 0; k < _dim1; k++) {
|
||||
|
@ -155,7 +155,7 @@ byte PaletteLUT::findNearest(byte c1, byte c2, byte c3, byte &nC1, byte &nC2, by
|
|||
return palIndex;
|
||||
}
|
||||
|
||||
SierraLite::SierraLite(int16 width, int16 height, PaletteLUT *palLUT) {
|
||||
SierraLight::SierraLight(int16 width, int16 height, PaletteLUT *palLUT) {
|
||||
assert((width > 0) && (height > 0));
|
||||
|
||||
_width = width;
|
||||
|
@ -170,24 +170,24 @@ SierraLite::SierraLite(int16 width, int16 height, PaletteLUT *palLUT) {
|
|||
_errors[1] = _errors[0] + 3 * (_width + 2*1);
|
||||
}
|
||||
|
||||
SierraLite::~SierraLite() {
|
||||
SierraLight::~SierraLight() {
|
||||
delete[] _errorBuf;
|
||||
}
|
||||
|
||||
void SierraLite::newFrame() {
|
||||
void SierraLight::newFrame() {
|
||||
_curLine = 0;
|
||||
memset(_errors[0], 0, 3 * _width * sizeof(int32));
|
||||
memset(_errors[1], 0, 3 * _width * sizeof(int32));
|
||||
}
|
||||
|
||||
void SierraLite::nextLine() {
|
||||
void SierraLight::nextLine() {
|
||||
// Clear the finished line, it will become the last line in the buffer
|
||||
memset(_errors[_curLine], 0, 3 * _width * sizeof(int32));
|
||||
|
||||
_curLine = (_curLine + 1) % 2;
|
||||
}
|
||||
|
||||
byte SierraLite::dither(byte c1, byte c2, byte c3, uint32 x) {
|
||||
byte SierraLight::dither(byte c1, byte c2, byte c3, uint32 x) {
|
||||
assert(_palLUT);
|
||||
|
||||
int32 eC1, eC2, eC3;
|
||||
|
@ -214,7 +214,7 @@ byte SierraLite::dither(byte c1, byte c2, byte c3, uint32 x) {
|
|||
return newPixel;
|
||||
}
|
||||
|
||||
inline void SierraLite::getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3) {
|
||||
inline void SierraLight::getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3) {
|
||||
int32 *errCur = _errors[_curLine];
|
||||
|
||||
x *= 3;
|
||||
|
@ -223,7 +223,7 @@ inline void SierraLite::getErrors(uint32 x, int32 &eC1, int32 &eC2, int32 &eC3)
|
|||
eC3 = errCur[x + 2] >> 2;
|
||||
}
|
||||
|
||||
inline void SierraLite::addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3) {
|
||||
inline void SierraLight::addErrors(uint32 x, int32 eC1, int32 eC2, int32 eC3) {
|
||||
int32 *errCur = _errors[_curLine];
|
||||
int32 *errNext = _errors[(_curLine + 1) % 2];
|
||||
|
||||
|
@ -251,7 +251,7 @@ Indeo3::Indeo3(int16 width, int16 height, PaletteLUT *palLUT) {
|
|||
_palLUT = palLUT;
|
||||
|
||||
_ditherSL = 0;
|
||||
setDither(kDitherSierraLite);
|
||||
setDither(kDitherSierraLight);
|
||||
|
||||
buildModPred();
|
||||
allocFrames();
|
||||
|
@ -297,8 +297,8 @@ void Indeo3::setDither(DitherAlgorithm dither) {
|
|||
_dither = dither;
|
||||
|
||||
switch(dither) {
|
||||
case kDitherSierraLite:
|
||||
_ditherSL = new SierraLite(_width, _height, _palLUT);
|
||||
case kDitherSierraLight:
|
||||
_ditherSL = new SierraLight(_width, _height, _palLUT);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -83,10 +83,10 @@ private:
|
|||
};
|
||||
|
||||
// The Sierra-2-4A ("Filter Light") dithering algorithm
|
||||
class SierraLite {
|
||||
class SierraLight {
|
||||
public:
|
||||
SierraLite(int16 width, int16 height, PaletteLUT *palLUT);
|
||||
~SierraLite();
|
||||
SierraLight(int16 width, int16 height, PaletteLUT *palLUT);
|
||||
~SierraLight();
|
||||
|
||||
void newFrame();
|
||||
void nextLine();
|
||||
|
@ -109,7 +109,7 @@ class Indeo3 {
|
|||
public:
|
||||
enum DitherAlgorithm {
|
||||
kDitherNone = 0,
|
||||
kDitherSierraLite
|
||||
kDitherSierraLight
|
||||
};
|
||||
|
||||
Indeo3(int16 width, int16 height, PaletteLUT *palLUT);
|
||||
|
@ -151,7 +151,7 @@ private:
|
|||
PaletteLUT *_palLUT;
|
||||
|
||||
DitherAlgorithm _dither;
|
||||
SierraLite *_ditherSL;
|
||||
SierraLight *_ditherSL;
|
||||
|
||||
struct BlitState {
|
||||
uint32 curX, curY;
|
||||
|
|
|
@ -1877,8 +1877,15 @@ bool Inter_v1::o1_loadSpriteContent(OpFuncParams ¶ms) {
|
|||
}
|
||||
|
||||
bool Inter_v1::o1_copySprite(OpFuncParams ¶ms) {
|
||||
_vm->_draw->_sourceSurface = load16();
|
||||
_vm->_draw->_destSurface = load16();
|
||||
if (_vm->_global->_inter_execPtr[1] == 0)
|
||||
_vm->_draw->_sourceSurface = load16();
|
||||
else
|
||||
_vm->_draw->_sourceSurface = _vm->_parse->parseValExpr();
|
||||
|
||||
if (_vm->_global->_inter_execPtr[1] == 0)
|
||||
_vm->_draw->_destSurface = load16();
|
||||
else
|
||||
_vm->_draw->_destSurface = _vm->_parse->parseValExpr();
|
||||
|
||||
_vm->_draw->_spriteLeft = _vm->_parse->parseValExpr();
|
||||
_vm->_draw->_spriteTop = _vm->_parse->parseValExpr();
|
||||
|
|
|
@ -216,6 +216,14 @@ public:
|
|||
|
||||
Video_v6(GobEngine *vm);
|
||||
virtual ~Video_v6() {}
|
||||
|
||||
private:
|
||||
void drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc);
|
||||
void drawYUVData(const byte *srcData, SurfaceDesc *destDesc,
|
||||
int16 width, int16 height, int16 x, int16 y);
|
||||
void drawYUV(SurfaceDesc *destDesc, int16 x, int16 y,
|
||||
int16 dataWidth, int16 dataHeight, int16 width, int16 height,
|
||||
const byte *dataY, const byte *dataU, const byte *dataV);
|
||||
};
|
||||
|
||||
class VideoDriver {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "gob/gob.h"
|
||||
#include "gob/video.h"
|
||||
#include "gob/indeo3.h"
|
||||
|
||||
namespace Gob {
|
||||
|
||||
|
@ -40,30 +41,103 @@ char Video_v6::spriteUncompressor(byte *sprBuf, int16 srcWidth, int16 srcHeight,
|
|||
|
||||
_vm->validateVideoMode(destDesc->_vidMode);
|
||||
|
||||
if (sprBuf[0] != 1)
|
||||
return 0;
|
||||
|
||||
if (sprBuf[1] != 3)
|
||||
return 0;
|
||||
|
||||
sprBuf += 2;
|
||||
|
||||
srcWidth = READ_LE_UINT16(sprBuf);
|
||||
sprBuf += 2;
|
||||
srcHeight = READ_LE_UINT16(sprBuf);
|
||||
sprBuf += 2;
|
||||
|
||||
if (sprBuf[0] == 0) {
|
||||
SurfaceDesc sourceDesc(0x13, srcWidth, srcHeight, sprBuf + 3);
|
||||
Video::drawSprite(&sourceDesc, destDesc, 0, 0, srcWidth - 1,
|
||||
srcHeight - 1, x, y, transp);
|
||||
if ((sprBuf[0] == 1) && (sprBuf[1] == 3)) {
|
||||
drawPacked(sprBuf, x, y, destDesc);
|
||||
return 1;
|
||||
} else {
|
||||
warning("Urban Stub: spriteUncompressor()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
warning("Urban Stub: spriteUncompressor(), sprBuf[0,1] = %d,%d",
|
||||
sprBuf[0], sprBuf[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Video_v6::drawPacked(const byte *sprBuf, int16 x, int16 y, SurfaceDesc *surfDesc) {
|
||||
const byte *data = sprBuf + 2;
|
||||
|
||||
int16 width = READ_LE_UINT16(data);
|
||||
int16 height = READ_LE_UINT16(data + 2);
|
||||
data += 4;
|
||||
|
||||
const byte *srcData = data;
|
||||
byte *uncBuf = 0;
|
||||
|
||||
if (*data++ != 0) {
|
||||
uint32 size = READ_LE_UINT32(data);
|
||||
|
||||
uncBuf = new byte[size];
|
||||
|
||||
//sub_4F020(data, buf);
|
||||
warning("Urban Stub: drawPacked: sub_4F020(data, uncBuf)");
|
||||
|
||||
srcData = uncBuf;
|
||||
}
|
||||
|
||||
drawYUVData(srcData, surfDesc, width, height, x, y);
|
||||
|
||||
delete[] uncBuf;
|
||||
}
|
||||
|
||||
void Video_v6::drawYUVData(const byte *srcData, SurfaceDesc *destDesc,
|
||||
int16 width, int16 height, int16 x, int16 y) {
|
||||
|
||||
int16 dataWidth = width;
|
||||
int16 dataHeight = height;
|
||||
|
||||
if (dataWidth & 0xF)
|
||||
dataWidth = (dataWidth & 0xFFF0) + 16;
|
||||
if (dataHeight & 0xF)
|
||||
dataHeight = (dataHeight & 0xFFF0) + 16;
|
||||
|
||||
const byte *dataY = srcData;
|
||||
const byte *dataU = dataY + (dataWidth * dataHeight);
|
||||
const byte *dataV = dataU + ((dataWidth * dataHeight) >> 4);
|
||||
|
||||
/*
|
||||
if (destDesc->field_14 == 1) {
|
||||
SurfaceDesc *tmpSurf = _vid_initSurfDesc(2, width, height, 0);
|
||||
|
||||
sub_46126(tmpSurf, 0, 0, dataWidth, dataHeight, width, height, dataY, dataU, dataV);
|
||||
|
||||
_vid_drawSprite(tmpSurf, destDesc, 0, 0, width - 1, height - 1, x, y, 0);
|
||||
|
||||
_vid_freeSurfDesc(tmpSurf);
|
||||
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
drawYUV(destDesc, x, y, dataWidth, dataHeight, width, height, dataY, dataU, dataV);
|
||||
|
||||
}
|
||||
|
||||
void Video_v6::drawYUV(SurfaceDesc *destDesc, int16 x, int16 y,
|
||||
int16 dataWidth, int16 dataHeight, int16 width, int16 height,
|
||||
const byte *dataY, const byte *dataU, const byte *dataV) {
|
||||
|
||||
byte *vidMem = destDesc->getVidMem() + y * width + x;
|
||||
|
||||
width = MIN(width, destDesc->getWidth());
|
||||
height = MIN(height, destDesc->getHeight());
|
||||
|
||||
SierraLight *dither = new SierraLight(width, height, _palLUT);
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
byte *dest = vidMem;
|
||||
const byte *srcY = dataY + i * dataWidth;
|
||||
const byte *srcU = dataU + (i >> 2) * (dataWidth >> 2);
|
||||
const byte *srcV = dataV + (i >> 2) * (dataWidth >> 2);
|
||||
|
||||
for (int j = 0; j < (width >> 2); j++, srcU++, srcV++) {
|
||||
for (int n = 0; n < 4; n++, dest++, srcY++) {
|
||||
byte dY = *srcY << 1, dU = *srcU << 1, dV = *srcV << 1;
|
||||
|
||||
*dest = dither->dither(dY, dU, dV, j * 4 + n);
|
||||
}
|
||||
}
|
||||
|
||||
dither->nextLine();
|
||||
vidMem += width;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Gob
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue