Add support for 4 quadrants
git-svn-id: svn://svn.cc65.org/cc65/trunk@5915 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -86,6 +86,102 @@ static enum Mode GetMode (const Collection* A)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void encodeSprite(StrBuf *D, enum Mode M, char ColorBits, char ColorMask, char LineBuffer[512],
|
||||||
|
int i, int LastOpaquePixel) {
|
||||||
|
/*
|
||||||
|
* The data starts with a byte count. It tells the number of bytes on this
|
||||||
|
* line + 1.
|
||||||
|
* Special case is a count of 1. It will change to next quadrant.
|
||||||
|
* Other special case is 0. It will end the sprite.
|
||||||
|
*
|
||||||
|
* Ordinary data packet. These are bits in a stream.
|
||||||
|
* 1=literal 0=packed
|
||||||
|
* 4 bit count (+1)
|
||||||
|
* for literal you put "count" values
|
||||||
|
* for packed you repeat the value "count" times
|
||||||
|
* Never use packed mode for one pixel
|
||||||
|
* If the last bit on a line is 1 you need to add a byte of zeroes
|
||||||
|
* A sequence 00000 ends a scan line
|
||||||
|
*
|
||||||
|
* All data is high nybble first
|
||||||
|
*/
|
||||||
|
char OutBuffer[512]; /* The maximum size is 508 pixels */
|
||||||
|
unsigned char OutIndex = 0;
|
||||||
|
unsigned char V = 0;
|
||||||
|
unsigned W = 0;
|
||||||
|
signed j;
|
||||||
|
signed k;
|
||||||
|
|
||||||
|
switch (M) {
|
||||||
|
case smAuto:
|
||||||
|
case smLiteral:
|
||||||
|
OutIndex = 0;
|
||||||
|
k = 0;
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
/* Fetch next pixel index into pixel buffer */
|
||||||
|
W = (W << ColorBits) | (LineBuffer[j] & ColorMask);
|
||||||
|
k += ColorBits;
|
||||||
|
if (k > 7) {
|
||||||
|
/* The byte is ready */
|
||||||
|
k -= 8;
|
||||||
|
V = (W >> k) & 0xFF;
|
||||||
|
OutBuffer[OutIndex++] = V;
|
||||||
|
if (!OutIndex) {
|
||||||
|
Error ("Sprite is too large for the Lynx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Output last bits */
|
||||||
|
if (k != 0) {
|
||||||
|
W = (W << (8-k));
|
||||||
|
k = 0;
|
||||||
|
V = W & 0xFF;
|
||||||
|
OutBuffer[OutIndex++] = V;
|
||||||
|
if (!OutIndex) {
|
||||||
|
Error ("Sprite is too large for the Lynx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Fix bug in Lynx where the last bit on a line is 1 */
|
||||||
|
if (V & 1) {
|
||||||
|
OutBuffer[OutIndex++] = 0;
|
||||||
|
if (!OutIndex) {
|
||||||
|
Error ("Sprite is too large for the Lynx");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Fix bug in Lynx where the count cannot be 1 */
|
||||||
|
if (OutIndex == 1) {
|
||||||
|
OutBuffer[OutIndex++] = 0;
|
||||||
|
}
|
||||||
|
/* Write the byte count to the end of the scanline */
|
||||||
|
if (OutIndex == 255) {
|
||||||
|
Error ("Sprite is too large for the Lynx");
|
||||||
|
}
|
||||||
|
SB_AppendChar (D, OutIndex+1);
|
||||||
|
/* Write scanline data */
|
||||||
|
for (j = 0; j < OutIndex; j++) {
|
||||||
|
SB_AppendChar (D, OutBuffer[j]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case smPacked:
|
||||||
|
/* Bug workaround: If last bit is 1 and it is in bit0 add a zero byte */
|
||||||
|
/* Note: These extra pixels will be painted also. There is no workaround for this */
|
||||||
|
if (LineBuffer[i - 1] & 0x01) {
|
||||||
|
LineBuffer[i++] = 0;
|
||||||
|
}
|
||||||
|
/* Logical problem workaround: The count can not be 1 so add an extra byte */
|
||||||
|
if (i == 1) {
|
||||||
|
LineBuffer[i++] = 0;
|
||||||
|
}
|
||||||
|
/* Write the byte count for this partial scanline */
|
||||||
|
SB_AppendChar (D, i);
|
||||||
|
for (i = 0; i < LineBuffer[0]; i++) {
|
||||||
|
SB_AppendChar (D, LineBuffer[i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case smPackedTransparent:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
||||||
/* Generate binary output in Lynx sprite format for the bitmap B. The output
|
/* Generate binary output in Lynx sprite format for the bitmap B. The output
|
||||||
@@ -117,10 +213,8 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
{
|
{
|
||||||
enum Mode M;
|
enum Mode M;
|
||||||
StrBuf* D;
|
StrBuf* D;
|
||||||
unsigned X, Y;
|
signed X, Y;
|
||||||
unsigned OX, OY;
|
unsigned OX, OY;
|
||||||
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
|
||||||
char OutBuffer[512]; /* The maximum size is 508 pixels */
|
|
||||||
char ColorBits;
|
char ColorBits;
|
||||||
char ColorMask;
|
char ColorMask;
|
||||||
|
|
||||||
@@ -136,11 +230,6 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
/* Get the sprite mode */
|
/* Get the sprite mode */
|
||||||
M = GetMode (A);
|
M = GetMode (A);
|
||||||
|
|
||||||
/* If the mode wasn't given, fallback to packed */
|
|
||||||
if (M == smAuto) {
|
|
||||||
M = smLiteral;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now check if bitmap indexes are ok */
|
/* Now check if bitmap indexes are ok */
|
||||||
if (GetBitmapColors (B) > 16) {
|
if (GetBitmapColors (B) > 16) {
|
||||||
Error ("Too many colors for a Lynx sprite");
|
Error ("Too many colors for a Lynx sprite");
|
||||||
@@ -165,17 +254,13 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
SB_Realloc (D, 63);
|
SB_Realloc (D, 63);
|
||||||
|
|
||||||
/* Convert the image for quadrant bottom right */
|
/* Convert the image for quadrant bottom right */
|
||||||
for (Y = OY; Y < GetBitmapHeight (B); ++Y) {
|
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||||
unsigned char V = 0;
|
|
||||||
unsigned char OutIndex;
|
|
||||||
unsigned W = 0;
|
|
||||||
signed i = 0;
|
signed i = 0;
|
||||||
signed j;
|
|
||||||
signed k;
|
|
||||||
signed LastOpaquePixel = -1;
|
signed LastOpaquePixel = -1;
|
||||||
|
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||||
|
|
||||||
/* Fill the LineBuffer for easier optimisation */
|
/* Fill the LineBuffer for easier optimisation */
|
||||||
for (X = OX; X < GetBitmapWidth (B); ++X) {
|
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||||
|
|
||||||
/* Fetch next bit into byte buffer */
|
/* Fetch next bit into byte buffer */
|
||||||
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||||
@@ -186,73 +271,7 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (M) {
|
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||||
case smLiteral:
|
|
||||||
OutIndex = 0;
|
|
||||||
for (j = 0; j < i; j++) {
|
|
||||||
/* Fetch next pixel index into pixel buffer */
|
|
||||||
W = (W << ColorBits) | (LineBuffer[j] & ColorMask);
|
|
||||||
k += ColorBits;
|
|
||||||
if (k > 7) {
|
|
||||||
/* The byte is ready */
|
|
||||||
k -= 8;
|
|
||||||
V = (W >> k) & 0xFF;
|
|
||||||
OutBuffer[OutIndex++] = V;
|
|
||||||
if (!OutIndex) {
|
|
||||||
Error ("Sprite is too large for the Lynx");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Output last bits */
|
|
||||||
if (k != 0) {
|
|
||||||
W = (W << (8-k));
|
|
||||||
k = 0;
|
|
||||||
V = W & 0xFF;
|
|
||||||
OutBuffer[OutIndex++] = V;
|
|
||||||
if (!OutIndex) {
|
|
||||||
Error ("Sprite is too large for the Lynx");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Fix bug in Lynx where the last bit on a line is 1 */
|
|
||||||
if (V & 1) {
|
|
||||||
OutBuffer[OutIndex++] = 0;
|
|
||||||
if (!OutIndex) {
|
|
||||||
Error ("Sprite is too large for the Lynx");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Fix bug in Lynx where the count cannot be 1 */
|
|
||||||
if (OutIndex == 1) {
|
|
||||||
OutBuffer[OutIndex++] = 0;
|
|
||||||
}
|
|
||||||
/* Write the byte count to the end of the scanline */
|
|
||||||
if (OutIndex == 255) {
|
|
||||||
Error ("Sprite is too large for the Lynx");
|
|
||||||
}
|
|
||||||
SB_AppendChar (D, OutIndex+1);
|
|
||||||
/* Write scanline data */
|
|
||||||
for (j = 0; j < OutIndex; j++) {
|
|
||||||
SB_AppendChar (D, OutBuffer[j]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case smPacked:
|
|
||||||
/* Bug workaround: If last bit is 1 and it is in bit0 add a zero byte */
|
|
||||||
/* Note: These extra pixels will be painted also. There is no workaround for this */
|
|
||||||
if (LineBuffer[i - 1] & 0x01) {
|
|
||||||
LineBuffer[i++] = 0;
|
|
||||||
}
|
|
||||||
/* Logical problem workaround: The count can not be 1 so add an extra byte */
|
|
||||||
if (i == 1) {
|
|
||||||
LineBuffer[i++] = 0;
|
|
||||||
}
|
|
||||||
/* Write the byte count for this partial scanline */
|
|
||||||
SB_AppendChar (D, i);
|
|
||||||
for (i = 0; i < LineBuffer[0]; i++) {
|
|
||||||
SB_AppendChar (D, LineBuffer[i]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case smPackedTransparent:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((OY == 0) && (OX == 0)) {
|
if ((OY == 0) && (OX == 0)) {
|
||||||
@@ -270,20 +289,23 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
|
|
||||||
/* Convert the image for quadrant top right */
|
/* Convert the image for quadrant top right */
|
||||||
for (Y = OY - 1; Y >= 0; --Y) {
|
for (Y = OY - 1; Y >= 0; --Y) {
|
||||||
unsigned char V = 0;
|
signed i = 0;
|
||||||
if (M == smLiteral) {
|
signed LastOpaquePixel = -1;
|
||||||
for (X = OX; X < GetBitmapWidth (B); ++X) {
|
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||||
|
|
||||||
/* Fetch next bit into byte buffer */
|
/* Fill the LineBuffer for easier optimisation */
|
||||||
V = (V << 4) | (GetPixel (B, X, Y).Index & 0x0f);
|
for (X = OX; X < (signed)GetBitmapWidth (B); ++X) {
|
||||||
|
|
||||||
/* Store full bytes into the output buffer */
|
/* Fetch next bit into byte buffer */
|
||||||
if ((X & 0x01) == 0x01) {
|
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||||
SB_AppendChar (D, V);
|
|
||||||
V = 0;
|
if (LineBuffer[i]) {
|
||||||
}
|
LastOpaquePixel = i;
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next quadrant */
|
/* Next quadrant */
|
||||||
@@ -291,41 +313,47 @@ StrBuf* GenLynxSprite (const Bitmap* B, const Collection* A)
|
|||||||
|
|
||||||
/* Convert the image for quadrant top left */
|
/* Convert the image for quadrant top left */
|
||||||
for (Y = OY - 1; Y >= 0; --Y) {
|
for (Y = OY - 1; Y >= 0; --Y) {
|
||||||
unsigned char V = 0;
|
signed i = 0;
|
||||||
if (M == smLiteral) {
|
signed LastOpaquePixel = -1;
|
||||||
for (X = OX - 1; X >= 0; --X) {
|
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||||
|
|
||||||
/* Fetch next bit into byte buffer */
|
/* Fill the LineBuffer for easier optimisation */
|
||||||
V = (V << 4) | (GetPixel (B, X, Y).Index & 0x0f);
|
for (X = OX - 1; X >= 0; --X) {
|
||||||
|
|
||||||
/* Store full bytes into the output buffer */
|
/* Fetch next bit into byte buffer */
|
||||||
if ((X & 0x01) == 0x01) {
|
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||||
SB_AppendChar (D, V);
|
|
||||||
V = 0;
|
if (LineBuffer[i]) {
|
||||||
}
|
LastOpaquePixel = i;
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next quadrant */
|
/* Next quadrant */
|
||||||
SB_AppendChar (D, 1);
|
SB_AppendChar (D, 1);
|
||||||
|
|
||||||
/* Convert the image for quadrant bottom left */
|
/* Convert the image for quadrant bottom left */
|
||||||
for (Y = OY; Y < GetBitmapHeight (B); ++Y) {
|
for (Y = OY; Y < (signed)GetBitmapHeight (B); ++Y) {
|
||||||
unsigned char V = 0;
|
signed i = 0;
|
||||||
if (M == smLiteral) {
|
signed LastOpaquePixel = -1;
|
||||||
for (X = OX - 1; X >= 0; --X) {
|
char LineBuffer[512]; /* The maximum size is 508 pixels */
|
||||||
|
|
||||||
/* Fetch next bit into byte buffer */
|
/* Fill the LineBuffer for easier optimisation */
|
||||||
V = (V << 4) | (GetPixel (B, X, Y).Index & 0x0f);
|
for (X = OX - 1; X >= 0; --X) {
|
||||||
|
|
||||||
/* Store full bytes into the output buffer */
|
/* Fetch next bit into byte buffer */
|
||||||
if ((X & 0x01) == 0x01) {
|
LineBuffer[i] = GetPixel (B, X, Y).Index & ColorMask;
|
||||||
SB_AppendChar (D, V);
|
|
||||||
V = 0;
|
if (LineBuffer[i]) {
|
||||||
}
|
LastOpaquePixel = i;
|
||||||
}
|
}
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encodeSprite(D, M, ColorBits, ColorMask, LineBuffer, i, LastOpaquePixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End sprite */
|
/* End sprite */
|
||||||
|
|||||||
Reference in New Issue
Block a user