cache room strip offsets (this should help performance on PalmOS)

svn-id: r8300
This commit is contained in:
Max Horn 2003-06-04 21:45:29 +00:00
parent 55abd7d5ec
commit ffef453d1a
4 changed files with 125 additions and 8 deletions

View File

@ -761,7 +761,7 @@ void Scumm::redrawBGStrip(int start, int num) {
setGfxUsageBit(s + i, USAGE_BIT_DIRTY);
gdi.drawBitmap(getResourceAddress(rtRoom, _roomResource) + _IM00_offs,
&virtscr[0], s, 0, _roomWidth, virtscr[0].height, s, num, 0);
&virtscr[0], s, 0, _roomWidth, virtscr[0].height, s, num, 0, _roomStrips);
}
void Scumm::restoreCharsetBg() {
@ -869,7 +869,7 @@ byte *Scumm::getMaskBuffer(int x, int y, int z) {
* and objects, used throughout all SCUMM versions.
*/
void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
int stripnr, int numstrip, byte flag) {
int stripnr, int numstrip, byte flag, StripTable *table) {
assert(ptr);
assert(height > 0);
byte *backbuff_ptr, *bgbak_ptr;
@ -988,7 +988,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
const int left = (stripnr << 3);
const int right = left + (numstrip << 3);
byte *dst = bgbak_ptr;
const byte *src = smap_ptr;
const byte *src;
byte color = 0, data = 0;
int run = 1;
bool dither = false;
@ -997,10 +997,18 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
memset(dither_table, 0, sizeof(dither_table));
int theX, theY;
if (table) {
src = smap_ptr + table->offsets[stripnr];
theX = left;
} else {
src = smap_ptr;
theX = 0;
}
// Draw image data. To do this, we decode the full RLE graphics data,
// but only draw those parts we actually want to display.
assert(height <= 128);
for (theX = 0; theX < width; theX++) {
for (; theX < width; theX++) {
ptr_dither_table = dither_table;
for (theY = 0; theY < height; theY++) {
if (--run == 0) {
@ -1030,11 +1038,19 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
}
}
// Draw mask (zplane) data
theY = 0;
theX = 0;
while (theX < width) {
if (table) {
src = smap_ptr + table->zoffsets[stripnr];
run = table->zrun[stripnr];
theX = left;
} else {
run = *src++;
theX = 0;
}
while (theX < width) {
if (run & 0x80) {
run &= 0x7f;
data = *src++;
@ -1074,6 +1090,7 @@ void Gdi::drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int wi
}
} while (--run);
}
run = *src++;
}
}
@ -1222,6 +1239,95 @@ next_iter:
}
}
/**
* Create and fill a table with offsets to the graphic and mask strips in the
* given V2 EGA bitmap.
* @param src the V2 EGA bitmap
* @param width the width of the bitmap
* @param height the height of the bitmap
* @param table the strip table to fill
* @return filled strip table
*/
StripTable *Gdi::generateStripTable(const byte *src, int width, int height, StripTable *table) {
// If no strip table was given to use, allocate a new one
if (table == 0)
table = (StripTable *)calloc(1, sizeof(StripTable));
const byte *bitmapStart = src;
byte color = 0, data = 0;
int x, y, length = 0;
byte run = 1;
for (x = 0 ; x < width; x++) {
if ((x % 8) == 0) {
assert(x < 160 * 8);
assert(run == 1);
table->offsets[x >> 3] = src - bitmapStart;
}
for (y = 0; y < height; y++) {
if (--run == 0) {
data = *src++;
if (data & 0x80) {
run = data & 0x7f;
} else {
run = data >> 4;
}
if (run == 0) {
run = *src++;
}
color = data & 0x0f;
}
}
}
// Directly after the graphics data, the mask follows
x = 0;
y = height;
width /= 8;
for (;;) {
length = *src++;
if (length & 0x80) {
length &= 0x7f;
data = *src++;
do {
if (y == height) {
assert(x < 120);
table->zoffsets[x] = src - bitmapStart - 1;
table->zrun[x] = length | 0x80;
}
if (--y == 0) {
if (--width == 0)
return table;
x++;
y = height;
}
} while (--length);
} else {
do {
data = *src++;
if (y == height) {
assert(x < 120);
table->zoffsets[x] = src - bitmapStart - 1;
table->zrun[x] = length;
}
if (--y == 0) {
if (--width == 0)
return table;
x++;
y = height;
}
} while (--length);
}
}
return table;
}
void Gdi::decodeStripEGA(byte *dst, const byte *src, int height) {
byte color = 0;
int run = 0, x = 0, y = 0, z;

View File

@ -96,6 +96,12 @@ struct BompDrawData {
BompDrawData() { memset(this, 0, sizeof(*this)); }
};
struct StripTable {
int offsets[160];
int zoffsets[120]; // FIXME: Why only 120 here?
int zrun[120]; // FIXME: Why only 120 here?
};
class Gdi {
friend class Scumm; // Mostly for the code in saveload.cpp ...
public:
@ -142,7 +148,8 @@ protected:
public:
void drawBitmap(const byte *ptr, VirtScreen *vs, int x, int y, const int width, const int height,
int stripnr, int numstrip, byte flag);
int stripnr, int numstrip, byte flag, StripTable *table = 0);
StripTable *generateStripTable(const byte *src, int width, int height, StripTable *table);
void clearCharsetMask();
void disableZBuffer() { _zbufferDisabled = true; }

View File

@ -715,7 +715,7 @@ protected:
void setVerbObject(uint room, uint object, uint verb);
// TODO: This should be moved into Scumm_v2 if posisble
// TODO: This should be moved into Scumm_v2 if possible
ScummVM::Rect v2_mouseover_boxes[7];
int8 v2_mouseover_box;
@ -804,6 +804,8 @@ protected:
uint16 xStrips, yStrips;
bool isDrawn;
} _flashlight;
StripTable *_roomStrips;
void getGraphicsPerformance();
void initScreens(int a, int b, int w, int h);

View File

@ -354,6 +354,7 @@ Scumm::Scumm (GameDetector *detector, OSystem *syst)
_switchRoomEffect = 0;
_doEffect = false;
memset(&_flashlight,0,sizeof(_flashlight));
_roomStrips = 0;
_bompActorPalettePtr = NULL;
_shakeEnabled= false;
_shakeFrame = 0;
@ -1390,6 +1391,7 @@ void Scumm::initRoomSubBlocks() {
//
if (_features & GF_OLD_BUNDLE) {
_IM00_offs = READ_LE_UINT16(roomptr + 0x0A);
_roomStrips = gdi.generateStripTable(roomptr + _IM00_offs, _roomWidth, _roomHeight, _roomStrips);
} else if (_features & GF_SMALL_HEADER)
_IM00_offs = findResourceData(MKID('IM00'), roomptr) - roomptr;
else if (_features & GF_AFTER_V8) {