Olav SørensenPushed v1.66 codef56d9f63 years agoHistory
528 lines · 13.4 KB · C
RawDownload
// for finding memory leaks in debug mode with Visual Studio#if defined _DEBUG && defined _MSC_VER#include <crtdbg.h>#endif #include <assert.h>#include <stdint.h>#include <stdbool.h>#include <stdlib.h>#include <string.h>#include "ft2_palette.h"#include "ft2_gfxdata.h"#include "ft2_bmp.h"#include "ft2_video.h" enum{	COMP_RGB = 0,	COMP_RLE8 = 1,	COMP_RLE4 = 2}; typedef struct bmpHeader_t{	uint32_t bfSizebfSize;	uint16_t bfReserved1;	uint16_t bfReserved2;	uint32_t bfOffBits;	uint32_t biSize;	int32_t biWidth;	int32_t biHeight;	uint16_t biPlanes;	uint16_t biBitCount;	uint32_t biCompression;	uint32_t biSizeImage;	int32_t biXPelsPerMeter;	int32_t biYPelsPerMeter;	int32_t biClrUsed;	int32_t biClrImportant;} bmpHeader_t; static uint32_t *loadBMPTo32Bit(const uint8_t *src);static uint8_t *loadBMPTo1Bit(const uint8_t *src);static uint8_t *loadBMPTo4BitPal(const uint8_t *src); bmp_t bmp; // globalized // if you match a color in this table, you have the real palette index (LUT pos)#define NUM_CUSTOM_PALS 17static const uint32_t bmpCustomPalette[NUM_CUSTOM_PALS] ={ // 0xC0FFEE = spacers	0x000000, 0x5397FF, 0x000067, 0x4BFFFF, 0xAB7787,	0xFFFFFF, 0x7F7F7F, 0xC0FFEE, 0x733747, 0xF7CBDB,	0x434343, 0xD3D3D3, 0xFFFF00, 0xC0FFEE, 0xC0FFEE,	0xC0FFEE, 0xFF0000 // last value = loop pin line}; static int8_t getFT2PalNrFromPixel(uint32_t pixel32){	for (int32_t i = 0; i < NUM_CUSTOM_PALS; i++)	{		if (pixel32 == bmpCustomPalette[i])			return (int8_t)i;	} 	return PAL_TRANSPR;} bool loadBMPs(void){	memset(&bmp, 0, sizeof (bmp)); 	bmp.ft2AboutLogo = loadBMPTo32Bit(ft2AboutLogoBMP);	bmp.font1 = loadBMPTo1Bit(font1BMP);	bmp.font2 = loadBMPTo1Bit(font2BMP);	bmp.font3 = loadBMPTo1Bit(font3BMP);	bmp.font4 = loadBMPTo1Bit(font4BMP);	bmp.font6 = loadBMPTo1Bit(font6BMP);	bmp.font7 = loadBMPTo1Bit(font7BMP);	bmp.font8 = loadBMPTo1Bit(font8BMP);	bmp.ft2LogoBadges = loadBMPTo4BitPal(ft2LogoBadgesBMP);	bmp.ft2ByBadges = loadBMPTo4BitPal(ft2ByBadgesBMP);	bmp.midiLogo = loadBMPTo4BitPal(midiLogoBMP);	bmp.nibblesLogo = loadBMPTo4BitPal(nibblesLogoBMP);	bmp.nibblesStages = loadBMPTo4BitPal(nibblesStagesBMP);	bmp.loopPins = loadBMPTo4BitPal(loopPinsBMP);	bmp.mouseCursors = loadBMPTo4BitPal(mouseCursorsBMP);	bmp.mouseCursorBusyClock = loadBMPTo4BitPal(mouseCursorBusyClockBMP);	bmp.mouseCursorBusyGlass = loadBMPTo4BitPal(mouseCursorBusyGlassBMP);	bmp.whitePianoKeys = loadBMPTo4BitPal(whitePianoKeysBMP);	bmp.blackPianoKeys = loadBMPTo4BitPal(blackPianoKeysBMP);	bmp.vibratoWaveforms = loadBMPTo4BitPal(vibratoWaveformsBMP);	bmp.scopeRec = loadBMPTo4BitPal(scopeRecBMP);	bmp.scopeMute = loadBMPTo4BitPal(scopeMuteBMP);	bmp.radiobuttonGfx = loadBMPTo4BitPal(radiobuttonGfxBMP);	bmp.checkboxGfx = loadBMPTo4BitPal(checkboxGfxBMP); 	if (bmp.ft2AboutLogo == NULL || bmp.font1 == NULL || bmp.font2 == NULL ||		bmp.font3 == NULL || bmp.font4 == NULL || bmp.font6 == NULL || bmp.font7 == NULL ||		bmp.font8 == NULL || bmp.ft2LogoBadges == NULL || bmp.ft2ByBadges == NULL ||		bmp.midiLogo == NULL || bmp.nibblesLogo == NULL || bmp.nibblesStages == NULL ||		bmp.loopPins == NULL || bmp.mouseCursors == NULL || bmp.mouseCursorBusyClock == NULL ||		bmp.mouseCursorBusyGlass == NULL || bmp.whitePianoKeys == NULL || bmp.blackPianoKeys == NULL ||		bmp.vibratoWaveforms == NULL || bmp.scopeRec == NULL || bmp.scopeMute == NULL ||		bmp.radiobuttonGfx == NULL || bmp.checkboxGfx == NULL)	{		showErrorMsgBox("Not enough memory!");		return false;	} 	return true;} void freeBMPs(void){	if (bmp.ft2AboutLogo != NULL) { free(bmp.ft2AboutLogo); bmp.ft2AboutLogo = NULL; }	if (bmp.font1 != NULL) { free(bmp.font1); bmp.font1 = NULL; }	if (bmp.font2 != NULL) { free(bmp.font2); bmp.font2 = NULL; }	if (bmp.font3 != NULL) { free(bmp.font3); bmp.font3 = NULL; }	if (bmp.font4 != NULL) { free(bmp.font4); bmp.font4 = NULL; }	if (bmp.font6 != NULL) { free(bmp.font6); bmp.font6 = NULL; }	if (bmp.font7 != NULL) { free(bmp.font7); bmp.font7 = NULL; }	if (bmp.font8 != NULL) { free(bmp.font8); bmp.font8 = NULL; }	if (bmp.ft2LogoBadges != NULL) { free(bmp.ft2LogoBadges); bmp.ft2LogoBadges = NULL; }	if (bmp.ft2ByBadges != NULL) { free(bmp.ft2ByBadges); bmp.ft2ByBadges = NULL; }	if (bmp.midiLogo != NULL) { free(bmp.midiLogo); bmp.midiLogo = NULL; }	if (bmp.nibblesLogo != NULL) { free(bmp.nibblesLogo); bmp.nibblesLogo = NULL; }	if (bmp.nibblesStages != NULL) { free(bmp.nibblesStages); bmp.nibblesStages = NULL; }	if (bmp.loopPins != NULL) { free(bmp.loopPins); bmp.loopPins = NULL; }	if (bmp.mouseCursors != NULL) { free(bmp.mouseCursors); bmp.mouseCursors = NULL; }	if (bmp.mouseCursorBusyClock != NULL) { free(bmp.mouseCursorBusyClock); bmp.mouseCursorBusyClock = NULL; }	if (bmp.mouseCursorBusyGlass != NULL) { free(bmp.mouseCursorBusyGlass); bmp.mouseCursorBusyGlass = NULL; }	if (bmp.whitePianoKeys != NULL) { free(bmp.whitePianoKeys); bmp.whitePianoKeys = NULL; }	if (bmp.blackPianoKeys != NULL) { free(bmp.blackPianoKeys); bmp.blackPianoKeys = NULL; }	if (bmp.vibratoWaveforms != NULL) { free(bmp.vibratoWaveforms); bmp.vibratoWaveforms = NULL; }	if (bmp.scopeRec != NULL) { free(bmp.scopeRec); bmp.scopeRec = NULL; }	if (bmp.scopeMute != NULL) { free(bmp.scopeMute); bmp.scopeMute = NULL; }	if (bmp.radiobuttonGfx != NULL) { free(bmp.radiobuttonGfx); bmp.radiobuttonGfx = NULL; }	if (bmp.checkboxGfx != NULL) { free(bmp.checkboxGfx); bmp.checkboxGfx = NULL; }} /* Very basic BMP loaders that supports top-down RLE-packed bitmaps, but only at 4-bit or 8-bit colors.** This is only meant to be used for BMPs that are carefully crafted for this program!*/ #ifdef _DEBUG #define CHECK_SRC_BOUNDARY     assert(src8      < src8End);#define CHECK_DST8_BOUNDARY    assert(tmp8      < allocEnd);#define CHECK_DST8_BOUNDARY_X  assert(&tmp8[x]  < allocEnd);#define CHECK_DST32_BOUNDARY   assert(tmp32     < allocEnd);#define CHECK_DST32_BOUNDARY_X assert(&tmp32[x] < allocEnd); #else#define CHECK_SRC_BOUNDARY#define CHECK_DST8_BOUNDARY#define CHECK_DST8_BOUNDARY_X#define CHECK_DST32_BOUNDARY#define CHECK_DST32_BOUNDARY_X#endif static uint32_t *loadBMPTo32Bit(const uint8_t *src){	int32_t len, byte, palIdx;	uint32_t *tmp32, color, color2, pal[256]; 	bmpHeader_t *hdr = (bmpHeader_t *)&src[2];	const uint8_t *pData = &src[hdr->bfOffBits];	const int32_t colorsInBitmap = 1 << hdr->biBitCount; 	if (hdr->biCompression == COMP_RGB || hdr->biClrUsed > 256 || colorsInBitmap > 256)		return NULL; 	uint32_t *outData = (uint32_t *)malloc(hdr->biWidth * hdr->biHeight * sizeof (uint32_t));	if (outData == NULL)		return NULL; #ifdef _DEBUG	const uint32_t *allocEnd = outData + (hdr->biWidth * hdr->biHeight);#endif 	// pre-fill image with first palette color	const int32_t palEntries = (hdr->biClrUsed == 0) ? colorsInBitmap : hdr->biClrUsed;	memcpy(pal, &src[0x36], palEntries * sizeof (uint32_t)); 	for (int32_t i = 0; i < hdr->biWidth * hdr->biHeight; i++)		outData[i] = pal[0]; 	const int32_t lineEnd = hdr->biWidth;	const uint8_t *src8 = pData;#ifdef _DEBUG	const uint8_t *src8End = src8 + hdr->biSizeImage;#endif	uint32_t *dst32 = outData;	int32_t x = 0;	int32_t y = hdr->biHeight - 1; 	while (true)	{		CHECK_SRC_BOUNDARY		byte = *src8++;		if (byte == 0) // escape control		{			CHECK_SRC_BOUNDARY			byte = *src8++;			if (byte == 0) // end of line			{				x = 0;				y--;			}			else if (byte == 1) // end of bitmap			{				break;			}			else if (byte == 2) // add to x/y position			{				CHECK_SRC_BOUNDARY				x += *src8++;				CHECK_SRC_BOUNDARY				y -= *src8++;			}			else // absolute bytes			{				if (hdr->biCompression == COMP_RLE8)				{					tmp32 = &dst32[(y * hdr->biWidth) + x];					for (int32_t i = 0; i < byte; i++)					{						CHECK_DST32_BOUNDARY						CHECK_SRC_BOUNDARY						*tmp32++ = pal[*src8++];					} 					if (byte & 1)						src8++; 					x += byte;				}				else				{ 					len = byte >> 1;					tmp32 = &dst32[y * hdr->biWidth];					for (int32_t i = 0; i < len; i++)					{						CHECK_SRC_BOUNDARY						palIdx = *src8++; 						CHECK_DST32_BOUNDARY_X						tmp32[x++] = pal[palIdx >> 4]; 						if (x < lineEnd)						{							CHECK_DST32_BOUNDARY_X							tmp32[x++] = pal[palIdx & 0xF];						}					} 					if (((byte + 1) >> 1) & 1)						src8++;				}			}		}		else		{			CHECK_SRC_BOUNDARY			palIdx = *src8++; 			if (hdr->biCompression == COMP_RLE8)			{				color = pal[palIdx];				tmp32 = &dst32[(y * hdr->biWidth) + x];				for (int32_t i = 0; i < byte; i++)				{					CHECK_DST32_BOUNDARY					*tmp32++ = color;				} 				x += byte;			}			else			{				color = pal[palIdx >> 4];				color2 = pal[palIdx & 0x0F]; 				len = byte >> 1;				tmp32 = &dst32[y * hdr->biWidth];				for (int32_t i = 0; i < len; i++)				{					CHECK_DST32_BOUNDARY_X					tmp32[x++] = color; 					if (x < lineEnd)					{						CHECK_DST32_BOUNDARY_X						tmp32[x++] = color2;					}				}			}		}	} 	return outData;} static uint8_t *loadBMPTo1Bit(const uint8_t *src) // supports 4-bit RLE only{	uint8_t palIdx, color, color2, *tmp8;	int32_t len, byte, i;	uint32_t pal[16]; 	bmpHeader_t *hdr = (bmpHeader_t *)&src[2];	const uint8_t *pData = &src[hdr->bfOffBits];	const int32_t colorsInBitmap = 1 << hdr->biBitCount; 	if (hdr->biCompression != COMP_RLE4 || hdr->biClrUsed > 16 || colorsInBitmap > 16)		return NULL; 	uint8_t *outData = (uint8_t *)malloc(hdr->biWidth * hdr->biHeight * sizeof (uint8_t));	if (outData == NULL)		return NULL; #ifdef _DEBUG	const uint8_t *allocEnd = outData + (hdr->biWidth * hdr->biHeight);#endif 	const int32_t palEntries = (hdr->biClrUsed == 0) ? colorsInBitmap : hdr->biClrUsed;	memcpy(pal, &src[0x36], palEntries * sizeof (uint32_t)); 	// pre-fill image with first palette color	color = !!pal[0];	for (i = 0; i < hdr->biWidth * hdr->biHeight; i++)		outData[i] = color; 	const int32_t lineEnd = hdr->biWidth;	const uint8_t *src8 = pData;#ifdef _DEBUG	const uint8_t *src8End = src8 + hdr->biSizeImage;#endif	uint8_t *dst8 = outData;	int32_t x = 0;	int32_t y = hdr->biHeight - 1; 	while (true)	{		CHECK_SRC_BOUNDARY		byte = *src8++;		if (byte == 0) // escape control		{			CHECK_SRC_BOUNDARY			byte = *src8++;			if (byte == 0) // end of line			{				x = 0;				y--;			}			else if (byte == 1) // end of bitmap			{				break;			}			else if (byte == 2) // add to x/y position			{				CHECK_SRC_BOUNDARY				x += *src8++;				CHECK_SRC_BOUNDARY				y -= *src8++;			}			else // absolute bytes			{				len = byte >> 1;				tmp8 = &dst8[y * hdr->biWidth];				for (i = 0; i < len; i++)				{					CHECK_SRC_BOUNDARY					palIdx = *src8++; 					CHECK_DST8_BOUNDARY_X					tmp8[x++] = !!pal[palIdx >> 4];										if (x < lineEnd)					{						CHECK_DST8_BOUNDARY_X						tmp8[x++] = !!pal[palIdx & 0xF];					}				} 				if (((byte + 1) >> 1) & 1)					src8++;			}		}		else		{			CHECK_SRC_BOUNDARY			palIdx = *src8++; 			color = !!pal[palIdx >> 4];			color2 = !!pal[palIdx & 0x0F]; 			len = byte >> 1;			tmp8 = &dst8[y * hdr->biWidth];			for (i = 0; i < len; i++)			{				CHECK_DST8_BOUNDARY_X				tmp8[x++] = color; 				if (x < lineEnd)				{					CHECK_DST8_BOUNDARY_X					tmp8[x++] = color2;				}			}		}	} 	return outData;} static uint8_t *loadBMPTo4BitPal(const uint8_t *src) // supports 4-bit RLE only{	uint8_t palIdx, *tmp8, pal1, pal2;	int32_t len, byte, i;	uint32_t pal[16]; 	bmpHeader_t *hdr = (bmpHeader_t *)&src[2];	const uint8_t *pData = &src[hdr->bfOffBits];	const int32_t colorsInBitmap = 1 << hdr->biBitCount; 	if (hdr->biCompression != COMP_RLE4 || hdr->biClrUsed > 16 || colorsInBitmap > 16)		return NULL; 	uint8_t *outData = (uint8_t *)malloc(hdr->biWidth * hdr->biHeight * sizeof (uint8_t));	if (outData == NULL)		return NULL; #ifdef _DEBUG	const uint8_t *allocEnd = outData + (hdr->biWidth * hdr->biHeight);#endif 	const int32_t palEntries = (hdr->biClrUsed == 0) ? colorsInBitmap : hdr->biClrUsed;	memcpy(pal, &src[0x36], palEntries * sizeof (uint32_t)); 	// pre-fill image with first palette color	palIdx = getFT2PalNrFromPixel(pal[0]);	for (i = 0; i < hdr->biWidth * hdr->biHeight; i++)		outData[i] = palIdx; 	const int32_t lineEnd = hdr->biWidth;	const uint8_t *src8 = pData;#ifdef _DEBUG	const uint8_t *src8End = src8 + hdr->biSizeImage;#endif	uint8_t *dst8 = outData;	int32_t x = 0;	int32_t y = hdr->biHeight - 1; 	while (true)	{		CHECK_SRC_BOUNDARY		byte = *src8++;		if (byte == 0) // escape control		{			CHECK_SRC_BOUNDARY			byte = *src8++;			if (byte == 0) // end of line			{				x = 0;				y--;			}			else if (byte == 1) // end of bitmap			{				break;			}			else if (byte == 2) // add to x/y position			{				CHECK_SRC_BOUNDARY				x += *src8++;				CHECK_SRC_BOUNDARY				y -= *src8++;			}			else // absolute bytes			{				tmp8 = &dst8[y * hdr->biWidth];				len = byte >> 1;				for (i = 0; i < len; i++)				{					CHECK_SRC_BOUNDARY					palIdx = *src8++; 					CHECK_DST8_BOUNDARY_X					tmp8[x++] = getFT2PalNrFromPixel(pal[palIdx >> 4]); 					if (x < lineEnd)					{						CHECK_DST8_BOUNDARY_X						tmp8[x++] = getFT2PalNrFromPixel(pal[palIdx & 0xF]);					}				} 				if (((byte + 1) >> 1) & 1)					src8++;

Lines 1–500 of 528.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t