Files
2026-08-31 21:04:48 +03:00

412 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*Understand, Correct, Improve ___
________/| _________________/\__/\____/ /_____
\ ____/ |/ __/ / / __ / \/ \ \ / __/
| __/ /\__ \ / __ \ / \ _/ \
|___\ \__\____ //__/\_____/\ /__/\ /_____/
`-------------\/------breeze-\ /crew-\/------'
\/
BMP to SXG (Speccy eXtended Graphics) [PentEvo 256]
----------------------------------------------------------
Written by breeze \ fishbone crew | http://fishbone.untergrund.net/
breeze@tut.by
18.02.2015
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
//---------------------------------------------------------------------------------------------
void printBits(char number){
char *bitsStr = "00000000\0";
for (int pos=8; pos>0; pos--) {
if(number > 0){
bitsStr[pos-1] = '0' + (number%2);
number = number/2;
} else {
bitsStr[pos-1] = '0';
}
}
printf(bitsStr);
}
unsigned int fileLength(FILE *f) {
int pos;
int end;
pos = ftell (f);
fseek (f, 0, SEEK_END);
end = ftell (f);
fseek (f, pos, SEEK_SET);
return end;
}
void printStrint (char *str) {
for (int i=0; str[i] != '\0'; i++){
printf ("%c", str[i]);
}
}
bool testHex (char testChar) {
bool valid = false;
if ((testChar > 0x2F && testChar < 0x39) || (testChar > 0x40 && testChar < 0x47)) {
valid = true;
}
return valid;
}
//---------------------------------------------------------------------------------------------
int main (int argc, char *argv[]) {
char *filename = NULL;
bool debugMode = false;
bool enableShim = true;
if ((argc > 1) && (argv[1][0] != '-')) {
filename = argv[1];
++argv;
--argc;
}
while ((argc > 1) && (argv[1][0] == '-' && argv[1][1] == '-')) {
//printf("arg %d = param %s\n", argc, argv[1]);
if (strcmp (argv[1], "--debug") == 0) {
debugMode = true;
} else if (strcmp (argv[1], "--64") == 0) {
enableShim = false;
}
++argv;
--argc;
}
// \033[22;30m - black
// \033[22;31m - red
// \033[22;32m - green
// \033[22;33m - brown
// \033[22;34m - blue
// \033[22;35m - magenta
// \033[22;36m - cyan
// \033[22;37m - gray
// \033[01;30m - dark gray
// \033[01;31m - light red
// \033[01;32m - light green
// \033[01;33m - yellow
// \033[01;34m - light blue
// \033[01;35m - light magenta
// \033[01;36m - light cyan
// \033[01;37m - white
printf("\nBMP to SXG (Speccy eXtended Graphics) v0.4 (alpha) 18 Feb 2015\n");
printf("-----------------------------------------------------------------------------------\n");
printf("Written by breeze\\fishbone crew | fishbone@speccy.su | http://fishbone.untergrund.net/\n");
printf("\n");
if (filename == NULL) {
printf("Usage: bmp2sxg <filename> [commands]\n");
printf("Commands:\n");
printf(" --debug enable output debug information (default disabled)\n");
printf(" --64 cut palette to atm 64 colors limit (default disabled)\n");
} else {
printf("Debug: ");
if (debugMode) {
printf("Enabled\n");
} else {
printf("Disabled\n");
}
printf("Full colors: ");
if (enableShim) {
printf("Enabled\n");
} else {
printf("Disabled\n");
}
printf("Work file: %s ", filename);
FILE *readfile = fopen(filename, "rb");
if (readfile != NULL) {
unsigned int filelen = fileLength(readfile);
if (filelen > 0) {
printf("(%i bytes)\n", filelen);
void *fileContent = malloc( filelen + 1 );
fread(fileContent, filelen, 1, readfile);
fclose(readfile);
memcpy ((void *)((unsigned int)fileContent + filelen), "\0", 1);
printf ("File analizing... ");
unsigned char *bmpData = (unsigned char *)fileContent;
unsigned char *beginData = (unsigned char *)fileContent;
if (*(bmpData) == 'B' && *(bmpData+1) == 'M') {
bmpData += 2;
printf("BMP format detected!\n");
unsigned long bmpSize = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
bmpData += 4; // reserved 4 bytes
unsigned long imageStart = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long headerSize = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpWidth = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpHeigth = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned short bmpLayers = *(bmpData) + (*(bmpData+1)*256);
bmpData += 2;
unsigned short bmpBits = *(bmpData) + (*(bmpData+1)*256);
bmpData += 2;
unsigned long bmpCompressType = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpCompressSize = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpHorizontal = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpVertical = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpColors = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
unsigned long bmpColorsActive = (*(bmpData) + (*(bmpData+1)*256)) + (*(bmpData+2) + (*(bmpData+3)*256))*256;
bmpData += 4;
printf("\nBMP header:\n");
printf("---------------------------------\n");
printf (" file size: %d bytes\n", bmpSize);
printf (" image width: %d px\n", bmpWidth);
printf (" image heigth: %d px\n", bmpHeigth);
printf (" image planes: %d\n", bmpLayers);
printf (" bits/pixel: %d\n", bmpBits);
//printf (" compress type: %d (0-NO, 1-RLE8, 2 - RLE4)\n", bmpCompressType);
printf (" compress type: %d ", bmpCompressType);
switch (bmpCompressType) {
case 0:
printf ("(none)");
break;
case 1:
printf ("(RLE 8-bit/pixel)");
break;
case 2:
printf ("(RLE 4-bit/pixel)");
break;
case 3:
printf ("(Bit field or Huffman 1D compression for BITMAPCOREHEADER2)");
break;
case 4:
printf ("(JPEG or RLE-24 compression for BITMAPCOREHEADER2)");
break;
case 5:
printf ("(PNG)");
break;
case 6:
printf ("(Bit field)");
break;
default:
printf ("(unknown)");
}
printf ("\n");
printf (" image size: %d bytes\n", bmpCompressSize);
printf (" x pixels per meter: %d\n", bmpHorizontal);
printf (" y pixels per meter: %d\n", bmpVertical);
printf (" colors in color table: %d\n", bmpColors);
printf (" important color count: %d\n\n", bmpColorsActive);
if (bmpCompressType == 0) {
printf("BMP palette:\n");
printf("---------------------------------\n");
unsigned char realColorz = bmpColors;
if ( realColorz == 0 ) {
realColorz = bmpBits * bmpBits;
}
if (realColorz > 0) {
unsigned char colorz[realColorz*2];
printf ("BMP use calculated colors: %d\n\n", realColorz);
if (debugMode) {
printf (" No # R G B R G B pentevo xRRrrrGG gggBBbbb\n");
}
int index = 0;
for (int i = 0; i<realColorz; i++) {
if (debugMode) {
printf("BMP color %3d[#%02X] ",i,i);
}
unsigned char b = *(bmpData);
bmpData++;
unsigned char g = *(bmpData);
bmpData++;
unsigned char r = *(bmpData);
bmpData++;
unsigned char x = *(bmpData); // reserved
bmpData++;
if (debugMode) {
printf("[#%02X,#%02X,#%02X] -> ",r,g,b);
}
unsigned char colorCodeL = 0;
unsigned char colorCodeH = 0;
r = (r/10.6 + 0.5);
g = (g/10.6 + 0.5);
b = (b/10.6 + 0.5);
if (enableShim) {
colorCodeL = (b & 31) | ((g & 7)<<5);
colorCodeH = ((r & 31)<<2) | ((g & 31)>>3);
} else {
colorCodeL = (b & 24);
colorCodeH = ((r & 24)<<2) | ((g & 24)>>3);
}
if (debugMode) {
printf("%3d,%3d,%3d ",r,g,b);
printf("-> %3d,%3d[#%02X%02X] ", colorCodeH, colorCodeL, colorCodeH, colorCodeL);
printBits(colorCodeH);
printf(" ");
printBits(colorCodeL);
printf("\n");
}
colorz[index] = colorCodeL;
index++;
colorz[index] = colorCodeH;
index++;
}
printf("\nBMP Bitmap data...\n");
printf("---------------------------------\n");
// bmpBits 1 - bitmap is monochrome
// bmpBits 4 - bitmap has a maximum of 16 colors
// bmpBits 8 - bitmap has a maximum of 256 colors
// bmpBits 16 - bitmap has a maximum of 65536 colors
// bmpBits 32 - bitmap has a maximum of 16777216 colors
printf("Bitmap bits - %d \n", bmpBits);
if (bmpBits == 4 || bmpBits == 8) {
unsigned long dataLen = ( bmpWidth * bmpHeigth );
if ( dataLen > 0 ) {
if (bmpBits == 4) {
dataLen = dataLen/2;
}
printf("Bitmap data length - %d bytes\n", dataLen);
unsigned char *bmpImageData=(unsigned char *)(beginData+imageStart);
unsigned char *memImageData = (unsigned char *)malloc(dataLen);
unsigned char *workImageData = (unsigned char *)(memImageData);
unsigned long spriteWidth = bmpWidth;
if (bmpBits == 4) {
spriteWidth = bmpWidth / 2;
}
for (int y = bmpHeigth - 1; y >= 0; y-- ) {
for (int x = 0; x < spriteWidth; x++){
unsigned char colorPixel = *(bmpImageData + x + ( y * spriteWidth ));
*workImageData = colorPixel;
workImageData++;
if (debugMode) {
printf("#%02X,",colorPixel);
}
}
if (debugMode) {
printf("\n");
}
}
unsigned char colorzFinal[realColorz*2];
for (int i=0; i<realColorz*2; i++) {
colorzFinal[i] = colorz[i];
}
// +#0000 #03 "SXG" - 3 байта сигнатура, что это формат файла
// +#0003 #01 1 байт формат изображения (1 - 16ц, 2 - 256ц)
// +#0004 #02 2 байта ширина изображения
// +#0006 #02 2 байта высота изображения
// (что бы можно было добавить ещё параметры)
// +#0008 #02 смещение от текущего адреса до начала данных палитры
// +#000a #02 смещение от текущего адреса до начала данных битмап
// Начало данных палитры
// +#000с #0200 512 байт палитра
// Начало данных битмап
// +#020с #xxxx данные битмап
char *saveFileName = strtok(filename, ".");
saveFileName = strcat(saveFileName,".sxg");
FILE *writeSxgFile = fopen(saveFileName, "wb");
if (writeSxgFile != NULL) {
unsigned char *sxgId = "\x7FSXG";
fwrite(sxgId, 1, 4, writeSxgFile);
unsigned char sxgType = 1;
if (bmpBits > 4) {
sxgType = 2;
}
fwrite(&sxgType, 1, 1, writeSxgFile);
short int sxgWidth = (short int)bmpWidth;
short int sxgHeigth = (short int)bmpHeigth;
fwrite(&bmpWidth, 1, sizeof(short int), writeSxgFile);
fwrite(&bmpHeigth, 1, sizeof(short int), writeSxgFile);
short int palStart = 2;
fwrite(&palStart, 1, sizeof(short int), writeSxgFile);
short int palSize = realColorz*2;
fwrite(&palSize, 1, sizeof(short int), writeSxgFile);
fwrite(colorzFinal, 1, palSize, writeSxgFile);
workImageData = memImageData;
unsigned long writeLen = dataLen;
fwrite(workImageData, 1, writeLen, writeSxgFile);
} else {
printf ("Error: Can't write file: %s", saveFileName);
}
free (memImageData);
} else {
printf("Error: Wrong bitmap legth!\n");
return 1;
}
} else {
printf("Error: support only 16 & 256 colors bmp!\n");
return 1;
}
} else {
printf("Error: Wrong BMP palette.\n");
return 1;
}
} else {
printf("Error: Compressed file not supported yet.\n");
return 1;
}
} else {
printf("Error: Wrong format of file - %s\n", filename);
return 1;
}
free (fileContent);
} else {
printf ("Error: Wrong size of file - %s\n", filename);
return 1;
}
} else {
printf ("Error: Can't opening file - %s\n", filename);
return 1;
}
}
return 0;
}