kolibrios-fun/programs/games/fara/trunk/gfxdef.cpp
2011-01-30 10:48:08 +00:00

286 lines
6.4 KiB
C++
Raw Permalink Blame History

#include "kosSyst.h"
#include "KosFile.h"
#include "gfxdef.h"
#include "crc32.h"
extern "C" void __stdcall lzma_decompress(
const void* source,
void* destination,
unsigned dest_length);
struct export_item
{
const char* name;
const void* func;
};
typedef void* (__stdcall *img_decode_t)(const void* data, unsigned len, void* parameters);
typedef void (__stdcall *img_to_rgb2_t)(const void* image, void* destination);
typedef void (__stdcall *img_destroy_t)(void* image);
typedef void (__stdcall *img_lib_init_t)(void); // really fastcall with 4 args, but called from asm code
img_lib_init_t img_lib_init = NULL;
img_decode_t img_decode = NULL;
img_to_rgb2_t img_to_rgb2 = NULL;
img_destroy_t img_destroy = NULL;
export_item* libini_exports = NULL;
static const char libini_name[] = "/sys/lib/libimg.obj";
extern "C" int strcmp(const char* str1, const char* str2);
#pragma intrinsic(strcmp)
void jpeg_decompress(
const void* source,
unsigned source_length,
void* destination,
unsigned dest_length)
{
if (!libini_exports)
{
__asm
{
mov eax, 68
mov ebx, 19
mov ecx, offset libini_name
int 40h
mov [libini_exports], eax
}
if (!libini_exports)
{
rtlDebugOutString("Cannot load libimg.obj");
kos_ExitApp();
}
for (export_item* p = libini_exports; p->name; p++)
{
if (!strcmp(p->name,"lib_init"))
img_lib_init = (img_lib_init_t)p->func;
else if (!strcmp(p->name,"img_decode"))
img_decode = (img_decode_t)p->func;
else if (!strcmp(p->name,"img_to_rgb2"))
img_to_rgb2 = (img_to_rgb2_t)p->func;
else if (!strcmp(p->name,"img_destroy"))
img_destroy = (img_destroy_t)p->func;
}
if (!img_lib_init || !img_decode || !img_to_rgb2 || !img_destroy)
{
rtlDebugOutString("Required exports were not found in libimg.obj");
kos_ExitApp();
}
__asm
{
mov eax, offset kos_malloc
mov ebx, offset kos_free
mov ecx, offset kos_realloc
call img_lib_init
}
}
void* image = img_decode(source, source_length, NULL);
if (!image)
{
rtlDebugOutString("JPEG error");
kos_ExitApp();
}
img_to_rgb2(image, destination);
img_destroy(image);
}
////// CKosBitmap
CKosBitmap::CKosBitmap()
{
this->bmpID = -1;
this->buffer = NULL;
this->sizeX = 0;
this->sizeY = 0;
}
CKosBitmap::~CKosBitmap()
{
if ( this->buffer != NULL ) delete this->buffer;
}
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><> ᦠ⮣<E1A6A0><><E4A0A9>
bool CKosBitmap::LoadFromArch( SCompBmpHeader *bmpArchDesc, CKosFile *fromFile, int ID )
{
Byte *tmpBuff;
//
if ( this->buffer != NULL )
{
delete this->buffer;
this->buffer = NULL;
}
//
this->buffer = new RGB[bmpArchDesc->sizeX * bmpArchDesc->sizeY];
//
tmpBuff = new Byte[bmpArchDesc->compressedSize];
//
fromFile->Seek( SEEK_SET, bmpArchDesc->physicalOffset );
if ( fromFile->Read( tmpBuff, bmpArchDesc->compressedSize ) == bmpArchDesc->compressedSize )
{
//
if ( bmpArchDesc->compressedSize == bmpArchDesc->uncompressedSize+1)
{
// JPEG image
jpeg_decompress( tmpBuff, bmpArchDesc->compressedSize,
this->buffer, bmpArchDesc->sizeX * bmpArchDesc->sizeY * 3);
}
else if ( bmpArchDesc->compressedSize != bmpArchDesc->uncompressedSize )
{
// LZMA-packed BMP
lzma_decompress( tmpBuff, this->buffer, bmpArchDesc->uncompressedSize);
}
else
{
//
memcpy( (Byte *)(this->buffer), tmpBuff, bmpArchDesc->compressedSize );
}
//
this->sizeX = bmpArchDesc->sizeX;
this->sizeY = bmpArchDesc->sizeY;
this->bmpID = ID;
}
//
delete tmpBuff;
//
return true;
}
// <20><EFBFBD><EBA2A5><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><E2A8AD>
void CKosBitmap::Draw( Word x, Word y )
{
//
if ( this->buffer != NULL )
//
kos_PutImage( this->buffer, this->sizeX, this->sizeY, x, y );
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E3AAA0><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RGB * CKosBitmap::GetBits()
{
return this->buffer;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><><E0A0A7><EFBFBD> <20><><EFBFBD><EFBFBD><E2A8AD>
void CKosBitmap::GetSize( Word &cx, Word &cy )
{
cx = this->sizeX;
cy = this->sizeY;
}
// ᮧ<><E1AEA7><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><E2A8AD> <20><> <20><><EFBFBD><EFBFBD>
void CKosBitmap::Scale(Word size, RGB *mainBits)
{
buffer = new RGB[(sizeX=blockSize)*(sizeY=blockSize*11)];
memset((Byte*)buffer,0,3*blockSize*blockSize*11);
RGB* tmpBuf = new RGB[blockSize*size];
for (int k=0;k<11;k++)
{
int delta = (blockSize - size)/2;
int i,j;
int a;
int d1 = blockSize/size;
int d2 = (blockSize-d1*(size))*256/size;
// ᣫ<><E1A3AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><E0A8A7><EFBFBD>
RGB* ptrBuf = tmpBuf;
for (j=0;j<blockSize;j++)
{
RGB* srcBits = mainBits + blockSize*blockSize*(k+1) + blockSize*j;
a = 0;
for (i=0;i<size;i++)
{
ptrBuf->b = srcBits->b + (srcBits[1].b-srcBits[0].b)*a/256;
ptrBuf->g = srcBits->g + (srcBits[1].g-srcBits[0].g)*a/256;
ptrBuf->r = srcBits->r + (srcBits[1].r-srcBits[0].r)*a/256;
ptrBuf++;
srcBits += d1;
a += d2;
if (a >= 256)
{
a -= 256;
srcBits++;
}
}
}
// ᣫ<><E1A3AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><E2A8AA><EFBFBD>
for (j=0;j<size;j++)
{
ptrBuf = buffer + blockSize*blockSize*k + blockSize*delta + delta+j;
RGB* srcBits = tmpBuf + j;
a = 0;
for (i=0;i<size;i++)
{
ptrBuf->b = srcBits->b + (srcBits[size].b-srcBits[0].b)*a/256;
ptrBuf->g = srcBits->g + (srcBits[size].g-srcBits[0].g)*a/256;
ptrBuf->r = srcBits->r + (srcBits[size].r-srcBits[0].r)*a/256;
ptrBuf += blockSize;
srcBits += d1*size;
a += d2;
if (a >= 256)
{
a -= 256;
srcBits += size;
}
}
}
}
delete tmpBuf;
}
////////////////////// CFishka ///////////////////////
CFishka::CFishka( CKosBitmap *fromBmp, int yOffset, RGB insColour )
{
int i, c;
//
this->bits = fromBmp->GetBits() + (yOffset * blockSize);
this->transColour = insColour;
//
this->highLighted = new RGB[blockSize * blockSize];
//
for ( i = 0; i < (blockSize * blockSize); i++ )
{
//
this->highLighted[i] = this->bits[i];
//
if ( this->highLighted[i] != this->transColour )
{
c = ( this->highLighted[i].b * 185 ) / 100;
this->highLighted[i].b = (c > 255) ? 255 : c;
c = ( this->highLighted[i].g * 185 ) / 100;
this->highLighted[i].g = (c > 255) ? 255 : c;
c = ( this->highLighted[i].r * 185 ) / 100;
this->highLighted[i].r = (c > 255) ? 255 : c;
}
}
}
//
CFishka::~CFishka()
{
//
delete this->highLighted;
}
//
RGB * CFishka::GetBits()
{
return this->bits;
}
//
RGB * CFishka::GetHighlightedBits()
{
return this->highLighted;
}