diff options
Diffstat (limited to 'sword2')
-rw-r--r-- | sword2/driver/d_draw.h | 2 | ||||
-rw-r--r-- | sword2/driver/render.cpp | 162 | ||||
-rw-r--r-- | sword2/driver/render.h | 8 |
3 files changed, 74 insertions, 98 deletions
diff --git a/sword2/driver/d_draw.h b/sword2/driver/d_draw.h index 5e30e4d79c..df085c127a 100644 --- a/sword2/driver/d_draw.h +++ b/sword2/driver/d_draw.h @@ -221,7 +221,7 @@ public: int32 initialiseBackgroundLayer(Parallax *p); void closeBackgroundLayer(void); - void plotPoint(uint16 x, uint16 y, uint8 colour); + void plotPoint(int16 x, int16 y, uint8 colour); void drawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour); #ifdef BACKEND_8BIT void plotYUV(byte *lut, int width, int height, byte *const *dat); diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp index edf91cd22c..b3d73df142 100644 --- a/sword2/driver/render.cpp +++ b/sword2/driver/render.cpp @@ -28,9 +28,6 @@ namespace Sword2 { #define MILLISECSPERCYCLE 83 -#define BLOCKWBITS 6 -#define BLOCKHBITS 6 - void Graphics::updateRect(Common::Rect *r) { _vm->_system->copyRectToScreen(_buffer + r->top * _screenWide + r->left, _screenWide, r->left, r->top, r->right - r->left, @@ -57,11 +54,11 @@ void Graphics::blitBlockSurface(BlockSurface *s, Common::Rect *r, Common::Rect * r->right = clipRect->right; byte *dst = _buffer + r->top * _screenWide + r->left; - int i, j; + int i; if (s->transparent) { for (i = 0; i < r->bottom - r->top; i++) { - for (j = 0; j < r->right - r->left; j++) { + for (int j = 0; j < r->right - r->left; j++) { if (src[j]) dst[j] = src[j]; } @@ -195,16 +192,15 @@ void Graphics::scaleImageGood(byte *dst, uint16 dstPitch, uint16 dstWidth, uint1 * @param colour colour of the point */ -void Graphics::plotPoint(uint16 x, uint16 y, uint8 colour) { - byte *buf = _buffer + 40 * RENDERWIDE; - int16 newx, newy; - - newx = x - _scrollX; - newy = y - _scrollY; +void Graphics::plotPoint(int16 x, int16 y, uint8 colour) { + byte *buf = _buffer + MENUDEEP * RENDERWIDE; + + x -= _scrollX; + y -= _scrollY; - if (newx >= 0 && newx < RENDERWIDE && newy >= 0 && newy < RENDERDEEP) { - buf[newy * RENDERWIDE + newx] = colour; - markAsDirty(newx, newy + 40, newx, newy + 40); + if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) { + buf[y * RENDERWIDE + x] = colour; + markAsDirty(x, y + MENUDEEP, x, y + MENUDEEP); } } @@ -218,22 +214,14 @@ void Graphics::plotPoint(uint16 x, uint16 y, uint8 colour) { */ // Uses Bressnham's incremental algorithm! + void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { - byte *buf = _buffer + 40 * RENDERWIDE; - int dx, dy; int dxmod, dymod; int ince, incne; int d; int x, y; int addTo; - x1 -= _scrollX; - y1 -= _scrollY; - x0 -= _scrollX; - y0 -= _scrollY; - - markAsDirty(MIN(x0, x1), MIN(y0, y1) + 40, MAX(x0, x1), MAX(y0, y1) + 40); - // Make sure we're going from left to right if (x1 < x0) { @@ -241,8 +229,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { SWAP(y0, y1); } - dx = x1 - x0; - dy = y1 - y0; + int dx = x1 - x0; + int dy = y1 - y0; if (dx < 0) dxmod = -dx; @@ -261,8 +249,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { incne = 2 * (dy - dx); x = x0; y = y0; - if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + x] = colour; + + plotPoint(x, y, colour); while (x < x1) { if (d <= 0) { @@ -273,8 +261,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { x++; y++; } - if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + x] = colour; + + plotPoint(x, y, colour); } } else { addTo = y0; @@ -288,8 +276,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { incne = 2 * (dy - dx); x = x0; y = y0; - if (x >= 0 && x < RENDERWIDE && addTo - y >= 0 && addTo - y < RENDERDEEP) - buf[(addTo - y) * RENDERWIDE + x] = colour; + + plotPoint(x, addTo - y, colour); while (x < x1) { if (d <= 0) { @@ -300,8 +288,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { x++; y++; } - if (x >= 0 && x < RENDERWIDE && addTo - y >= 0 && addTo - y < RENDERDEEP) - buf[(addTo - y) * RENDERWIDE + x] = colour; + + plotPoint(x, addTo - y, colour); } } } else { @@ -320,8 +308,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { incne = 2 * (dx - dy); x = x0; y = y0; - if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + x] = colour; + + plotPoint(x, y, colour); while (y < y1) { if (d <= 0) { @@ -332,8 +320,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { x++; y++; } - if (x >= 0 && x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + x] = colour; + + plotPoint(x, y, colour); } } else { addTo = x0; @@ -347,8 +335,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { incne = 2 * (dx - dy); x = x0; y = y0; - if (addTo - x >= 0 && addTo - x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + addTo - x] = colour; + + plotPoint(addTo - x, y, colour); while (y < y1) { if (d <= 0) { @@ -359,8 +347,8 @@ void Graphics::drawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) { x++; y++; } - if (addTo - x >= 0 && addTo - x < RENDERWIDE && y >= 0 && y < RENDERDEEP) - buf[y * RENDERWIDE + addTo - x] = colour; + + plotPoint(addTo - x, y, colour); } } } @@ -412,7 +400,7 @@ void Graphics::renderParallax(Parallax *p, int16 l) { if (_blockSurfaces[l][i + j * _xBlocks[l]]) { r.left = i * BLOCKWIDTH - x; r.right = r.left + BLOCKWIDTH; - r.top = j * BLOCKHEIGHT - y + 40; + r.top = j * BLOCKHEIGHT - y + MENUDEEP; r.bottom = r.top + BLOCKHEIGHT; blitBlockSurface(_blockSurfaces[l][i + j * _xBlocks[l]], &r, &clipRect); } @@ -558,31 +546,21 @@ void Graphics::setScrollTarget(int16 sx, int16 sy) { */ int32 Graphics::initialiseBackgroundLayer(Parallax *p) { - byte *memchunk; - uint8 zeros; - uint16 count; uint16 i, j, k; - uint16 x; byte *data; byte *dst; - ParallaxLine line; - byte *pLine; debug(2, "initialiseBackgroundLayer"); - // This function is called to re-initialise the layers if they have - // been lost. We know this if the layers have already been assigned. - - if (_layer == MAXLAYERS) - closeBackgroundLayer(); + assert(_layer < MAXLAYERS); if (!p) { _layer++; return RD_OK; } - _xBlocks[_layer] = (p->w + BLOCKWIDTH - 1) >> BLOCKWBITS; - _yBlocks[_layer] = (p->h + BLOCKHEIGHT - 1) >> BLOCKHBITS; + _xBlocks[_layer] = (p->w + BLOCKWIDTH - 1) / BLOCKWIDTH; + _yBlocks[_layer] = (p->h + BLOCKHEIGHT - 1) / BLOCKHEIGHT; _blockSurfaces[_layer] = (BlockSurface **) calloc(_xBlocks[_layer] * _yBlocks[_layer], sizeof(BlockSurface *)); if (!_blockSurfaces[_layer]) @@ -590,66 +568,70 @@ int32 Graphics::initialiseBackgroundLayer(Parallax *p) { // Decode the parallax layer into a large chunk of memory - memchunk = (byte *) calloc(_xBlocks[_layer] * _yBlocks[_layer], BLOCKWIDTH * BLOCKHEIGHT); + byte *memchunk = (byte *) calloc(_xBlocks[_layer] * _yBlocks[_layer], BLOCKWIDTH * BLOCKHEIGHT); if (!memchunk) return RDERR_OUTOFMEMORY; for (i = 0; i < p->h; i++) { - if (p->offset[i] == 0) + if (!p->offset[i]) continue; - pLine = (byte *) p + FROM_LE_32(p->offset[i]); - line.packets = READ_LE_UINT16(pLine); - line.offset = READ_LE_UINT16(pLine + 2); - data = pLine + sizeof(ParallaxLine); - x = line.offset; + byte *pLine = (byte *) p + FROM_LE_32(p->offset[i]); + uint16 packets = READ_LE_UINT16(pLine); + uint16 offset = READ_LE_UINT16(pLine + 2); - dst = memchunk + i * p->w + x; + data = pLine + 4; + dst = memchunk + i * p->w + offset; - zeros = 0; - if (line.packets == 0) { + if (!packets) { memcpy(dst, data, p->w); continue; } - for (j = 0; j < line.packets; j++) { + bool zeros = false; + + for (j = 0; j < packets; j++) { if (zeros) { dst += *data; - x += *data; + offset += *data; data++; - zeros = 0; - } else if (*data == 0) { + zeros = false; + } else if (!*data) { data++; - zeros = 1; + zeros = true; } else { - count = *data++; + uint16 count = *data++; memcpy(dst, data, count); data += count; dst += count; - x += count; - zeros = 1; + offset += count; + zeros = true; } } } - // Now create the surfaces! + // The large memory chunk is now divided into a number of smaller + // surfaces. For most parallax layers, we'll end up using less memory + // this way, and it will be faster to draw since completely transparent + // surfaces are discarded. for (i = 0; i < _xBlocks[_layer] * _yBlocks[_layer]; i++) { bool block_has_data = false; bool block_is_transparent = false; - data = memchunk + (p->w * BLOCKHEIGHT * (i / _xBlocks[_layer])) + BLOCKWIDTH * (i % _xBlocks[_layer]); + int x = BLOCKWIDTH * (i % _xBlocks[_layer]); + int y = BLOCKHEIGHT * (i / _xBlocks[_layer]); - // FIXME: The 'block_is_transparent' flag should only consider - // data that is inside the parallax layer. Still, it won't do - // any harm to leave it this way... + data = memchunk + p->w * y + x; for (j = 0; j < BLOCKHEIGHT; j++) { for (k = 0; k < BLOCKWIDTH; k++) { - if (data[j * p->w + k]) - block_has_data = true; - else - block_is_transparent = true; + if (x + k < p->w && y + j < p->h) { + if (data[j * p->w + k]) + block_has_data = true; + else + block_is_transparent = true; + } } } @@ -685,13 +667,13 @@ int32 Graphics::initialiseBackgroundLayer(Parallax *p) { void Graphics::closeBackgroundLayer(void) { debug(2, "CloseBackgroundLayer"); - for (int j = 0; j < MAXLAYERS; j++) { - if (_blockSurfaces[j]) { - for (int i = 0; i < _xBlocks[j] * _yBlocks[j]; i++) - if (_blockSurfaces[j][i]) - free(_blockSurfaces[j][i]); - free(_blockSurfaces[j]); - _blockSurfaces[j] = NULL; + for (int i = 0; i < MAXLAYERS; i++) { + if (_blockSurfaces[i]) { + for (int j = 0; j < _xBlocks[i] * _yBlocks[i]; j++) + if (_blockSurfaces[i][j]) + free(_blockSurfaces[i][j]); + free(_blockSurfaces[i]); + _blockSurfaces[i] = NULL; } } @@ -710,7 +692,7 @@ void Graphics::plotYUV(byte *lut, int width, int height, byte *const *dat) { for (y = 0; y < height; y += 2) { for (x = 0; x < width; x += 2) { - int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH+1)) + ((dat[1][cpos] + ROUNDADD)>>SHIFT)) * (BITDEPTH+1); + int i = ((((dat[2][cpos] + ROUNDADD) >> SHIFT) * (BITDEPTH + 1)) + ((dat[1][cpos] + ROUNDADD) >> SHIFT)) * (BITDEPTH + 1); cpos++; buf[linepos ] = lut[i + ((dat[0][ ypos ] + ROUNDADD) >> SHIFT)]; diff --git a/sword2/driver/render.h b/sword2/driver/render.h index 619acea867..2bf0ff2669 100644 --- a/sword2/driver/render.h +++ b/sword2/driver/render.h @@ -25,13 +25,7 @@ namespace Sword2 { #define RENDERWIDE 640 -#define ALIGNRENDERDEEP 480 -#define RENDERDEEP (ALIGNRENDERDEEP - (MENUDEEP * 2)) - -struct ParallaxLine { - uint16 packets; - uint16 offset; -}; +#define RENDERDEEP (480 - (MENUDEEP * 2)) } // End of namespace Sword2 |