| 1499 | |
| 1500 | uint8 *src, *dst; |
| 1501 | uint8 *sprite, *newSprite; |
| 1502 | uint8 pixel, red, green, blue; |
| 1503 | int16 i, j; |
| 1504 | int16 freeSprite = 0; |
| 1505 | ScummVM::Rect rd, rs; |
| 1506 | |
| 1507 | if (!(s->type & RDSPR_DISPLAYALIGN)) { |
| 1508 | s->x += parallaxScrollx; |
| 1509 | s->y += parallaxScrolly; |
| 1510 | } |
| 1511 | |
| 1512 | // The topmost 40 pixels are reserved by the GUI. |
| 1513 | |
| 1514 | s->y += 40; |
| 1515 | |
| 1516 | if (s->type & RDSPR_NOCOMPRESSION) |
| 1517 | sprite = s->data; |
| 1518 | else { |
| 1519 | sprite = (uint8 *) malloc(s->w * s->h); |
| 1520 | if (!sprite) |
| 1521 | return RDERR_OUTOFMEMORY; |
| 1522 | freeSprite = 1; |
| 1523 | if (s->type >> 8 == RDSPR_RLE16 >> 8) { |
| 1524 | if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) |
| 1525 | return RDERR_DECOMPRESSION; |
| 1526 | } else { |
| 1527 | if (DecompressRLE256(sprite, s->data, s->w * s->h)) |
| 1528 | return RDERR_DECOMPRESSION; |
| 1529 | } |
| 1530 | |
| 1531 | if (s->type & RDSPR_FLIP) { |
| 1532 | newSprite = (uint8 *) malloc(s->w * s->h); |
| 1533 | if (newSprite == NULL) { |
| 1534 | free(sprite); |
| 1535 | return RDERR_OUTOFMEMORY; |
| 1536 | } |
| 1537 | MirrorSprite(newSprite, sprite, s->w, s->h); |
| 1538 | free(sprite); |
| 1539 | sprite = newSprite; |
| 1540 | } |
| 1541 | } |
| 1542 | |
| 1543 | |
| 1544 | if (s->type & RDSPR_BLEND) { |
| 1545 | // We want to blend the sprite FROM the RECT rs. |
| 1546 | // We want to blend the sprite TO the RECT rd. |
| 1547 | rd.left = s->x - scrollx; |
| 1548 | rd.right = rd.left + s->w; |
| 1549 | rd.top = s->y - scrolly; |
| 1550 | rd.bottom = rd.top + s->h; |
| 1551 | |
| 1552 | rs.top = 0; |
| 1553 | rs.bottom = s->h; |
| 1554 | rs.left = 0; |
| 1555 | rs.right = s->w; |
| 1556 | |
| 1557 | //Now do the clipping - top |
| 1558 | if (rd.top < 40) { |
| 1559 | rs.top = (40 - rd.top); |
| 1560 | rd.top = 40; |
| 1561 | } |
| 1562 | //Clip the bottom |
| 1563 | if (rd.bottom > RENDERDEEP) { |
| 1564 | rs.bottom -= (rd.bottom - RENDERDEEP); |
| 1565 | rd.bottom = RENDERDEEP; |
| 1566 | } |
| 1567 | //Clip the left |
| 1568 | if (rd.left < 0) { |
| 1569 | rs.left -= rd.left; |
| 1570 | rd.left = 0; |
| 1571 | } |
| 1572 | //Clip the right |
| 1573 | if (rd.right > RENDERWIDE) { |
| 1574 | rs.right -= (rd.right - RENDERWIDE); |
| 1575 | rd.right = RENDERWIDE; |
| 1576 | } |
| 1577 | |
| 1578 | if (s->blend & 0x01) { |
| 1579 | red = s->blend >> 8; |
| 1580 | for (i = 0; i < rs.bottom - rs.top; i++) { |
| 1581 | src = sprite + (rs.top + i) * s->w + rs.left; |
| 1582 | dst = (uint8 *) lpBackBuffer->_pixels + lpBackBuffer->_width * (rd.top + i) + rd.left; |
| 1583 | for (j = 0; j < rs.right - rs.left; j++) { |
| 1584 | if (*src) { |
| 1585 | pixel = *dst; |
| 1586 | *dst = paletteMatch[(((palCopy[*src][0] * red + palCopy[pixel][0] * (8 - red)) >> 5) << 12) + |
| 1587 | (((palCopy[*src][1] * red + palCopy[pixel][1] * (8 - red)) >> 5) << 6) + |
| 1588 | (((palCopy[*src][2] * red + palCopy[pixel][2] * (8 - red)) >> 5))]; |
| 1589 | } |
| 1590 | src++; |
| 1591 | dst++; |
| 1592 | } |
| 1593 | } |
| 1594 | } else if (s->blend & 0x02) { |
| 1595 | red = palCopy[s->blend >> 8][0]; |
| 1596 | green = palCopy[s->blend >> 8][0]; |
| 1597 | blue = palCopy[s->blend >> 8][0]; |
| 1598 | for (i = 0; i < rs.bottom - rs.top; i++) { |
| 1599 | src = sprite + (rs.top + i) * s->w + rs.left; |
| 1600 | dst = (uint8 *) lpBackBuffer->_pixels + lpBackBuffer->_width * (rd.top + i) + rd.left; |
| 1601 | for (j = 0; j < rs.right - rs.left; j++) { |
| 1602 | if (*src) { |
| 1603 | pixel = *dst; |
| 1604 | *dst = paletteMatch[((((*src * red + (16 - *src) * palCopy[pixel][0]) >> 4) >> 2) << 12) + |
| 1605 | ((((*src * green + (16 - *src) * palCopy[pixel][1]) >> 4) >> 2) << 6) + |
| 1606 | (((*src * blue + (16 - *src) * palCopy[pixel][2]) >> 4) >> 2)]; |
| 1607 | } |
| 1608 | src++; |
| 1609 | dst++; |
| 1610 | } |
| 1611 | } |
| 1612 | } else { |
| 1613 | if (freeSprite) |
| 1614 | free(sprite); |
| 1615 | warning("Invalid blended sprite"); |
| 1616 | return RDERR_UNKNOWNTYPE; |
| 1617 | } |
| 1618 | |
| 1619 | // Upload the sprite area to the backend. |
| 1620 | lpBackBuffer->upload(&rd); |
| 1621 | } else { |
| 1622 | // Set startx and starty for the screen buffer |
| 1623 | |
| 1624 | if (s->type & RDSPR_DISPLAYALIGN) |
| 1625 | rd.top = s->y; |
| 1626 | else |
| 1627 | rd.top = s->y - scrolly; |
| 1628 | |
| 1629 | if (s->type & RDSPR_DISPLAYALIGN) |
| 1630 | rd.left = s->x; |
| 1631 | else |
| 1632 | rd.left = s->x - scrollx; |
| 1633 | |
| 1634 | rs.left = 0; |
| 1635 | rs.right = s->w; |
| 1636 | rs.top = 0; |
| 1637 | rs.bottom = s->h; |
| 1638 | |
| 1639 | if (s->scale & 0xFF) { |
| 1640 | // FIXME: For now, turn scaling off. |
| 1641 | warning("FIXME: Implement scaling"); |
| 1642 | s->scale &= ~0xFF; |
| 1643 | } |
| 1644 | |
| 1645 | if (s->scale & 0xff) { |
| 1646 | rd.right = rd.left + s->scaledWidth; |
| 1647 | rd.bottom = rd.top + s->scaledHeight; |
| 1648 | // Do clipping |
| 1649 | if (rd.top < 40) { |
| 1650 | rs.top = (40 - rd.top) * 256 / s->scale; |
| 1651 | rd.top = 40; |
| 1652 | } |
| 1653 | if (rd.bottom > 440) { |
| 1654 | rs.bottom -= ((rd.bottom - 440) * 256 / s->scale); |
| 1655 | rd.bottom = 440; |
| 1656 | } |
| 1657 | if (rd.left < 0) { |
| 1658 | rs.left = (0 - rd.left) * 256 / s->scale; |
| 1659 | rd.left = 0; |
| 1660 | } |
| 1661 | if (rd.right > 640) { |
| 1662 | rs.right -= ((rd.right - 640) * 256 / s->scale); |
| 1663 | rd.right = 640; |
| 1664 | } |
| 1665 | } else { |
| 1666 | rd.right = rd.left + s->w; |
| 1667 | rd.bottom = rd.top + s->h; |
| 1668 | |
| 1669 | // Do clipping |
| 1670 | if (rd.top < 40) { |
| 1671 | rs.top = 40 - rd.top; |
| 1672 | rd.top = 40; |
| 1673 | } |
| 1674 | if (rd.bottom > 440) { |
| 1675 | rs.bottom -= (rd.bottom - 440); |
| 1676 | rd.bottom = 440; |
| 1677 | } |
| 1678 | if (rd.left < 0) { |
| 1679 | rs.left = 0 - rd.left; |
| 1680 | rd.left = 0; |
| 1681 | } |
| 1682 | if (rd.right > 640) { |
| 1683 | rs.right -= (rd.right - 640); |
| 1684 | rd.right = 640; |
| 1685 | } |
| 1686 | } |
| 1687 | |
| 1688 | src = sprite + rs.top * s->w + rs.left; |
| 1689 | dst = (uint8 *) lpBackBuffer->_pixels + lpBackBuffer->_width * rd.top + rd.left; |
| 1690 | if (s->type & RDSPR_TRANS) { |
| 1691 | for (i = 0; i < rs.bottom - rs.top; i++) { |
| 1692 | for (j = 0; j < rs.right - rs.left; j++) { |
| 1693 | if (src[j]) |
| 1694 | dst[j] = src[j]; |
| 1695 | } |
| 1696 | src += s->w; |
| 1697 | dst += lpBackBuffer->_width; |
| 1698 | } |
| 1699 | } else { |
| 1700 | for (i = 0; i < rs.bottom - rs.top; i++) { |
| 1701 | memcpy(dst, src, rs.right - rs.left); |
| 1702 | src += s->w; |
| 1703 | dst += lpBackBuffer->_width; |
| 1704 | } |
| 1705 | } |
| 1706 | |
| 1707 | lpBackBuffer->upload(&rd); |
| 1708 | |
| 1709 | if (freeSprite) |
| 1710 | free(sprite); |
| 1711 | } |
| 1712 | |
| 1713 | // I'm guessing that the rest of the original code is simply to draw |
| 1714 | // the sprite in "software mode" at different quality setting. If so, |
| 1715 | // we should probably adapt some of it. Later. |
| 1716 | |