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:
Sven Hesse 2008-12-11 21:57:47 +00:00
parent 443158fd89
commit c65886a3ea
8 changed files with 167 additions and 44 deletions

View file

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

View file

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

View file

@ -116,6 +116,7 @@ public:
byte *_totFileData;
int16 _extHandle;
int16 _lomHandle;
char _totToLoad[20];

View file

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

View file

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

View file

@ -1877,8 +1877,15 @@ bool Inter_v1::o1_loadSpriteContent(OpFuncParams &params) {
}
bool Inter_v1::o1_copySprite(OpFuncParams &params) {
_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();

View file

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

View file

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