2018-09-09: Updated to version 59

Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
Gwenhael Le Moine 2024-03-20 07:46:28 +01:00
parent d048b845e4
commit 311f1aa6b5
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
15 changed files with 8379 additions and 139 deletions

BIN
Emu48.dll

Binary file not shown.

BIN
Emu48.exe

Binary file not shown.

View file

@ -83,8 +83,7 @@ h3 { color:red; font-size:1.1em; }
<a href="#ss12.2">12.2 About Emu48...</a>
</span></p>
<p><a class="nav1" href="#s13">13. DDE Server</a></p>
<p><a class="nav1" href="#s14">14. Emu48+ Changes</a></p>
<p><a class="nav1" href="#s15">15. License</a></p>
<p><a class="nav1" href="#s14">14. License</a></p>
</div>
<div id="main">
<h1><a name=s1>1. General</a></h1>
@ -96,9 +95,9 @@ h3 { color:red; font-size:1.1em; }
Emu48 v1.0 under the GPL. Without this decision newer versions of the
emulator wouldn't have been possible or ports to other similar
calculators wouldn't have been made. Also a big thank to Jean-Yves
Avenard for his technical assistance in the beginning. And finally I
want to thank all the unnamed authors for publishing material about
these calculators.</p>
Avenard for his technical assistance in the beginning. Lode Vandevenne
spend the PNG image decoder and finally I want to thank all the
unnamed authors for publishing material about these calculators.</p>
<h1><a name=s3>3. ROM Images</a></h1>
<p>Emu48 needs an image of a calculator ROM to be able to run. ROM
images are valid in a packed (even address lower nibble, odd address
@ -590,51 +589,9 @@ h3 { color:red; font-size:1.1em; }
<td width="66%" align="center">HP object (normal HP object)</td>
</tr>
</table>
<h1><a name=s14>14. Emu48+ Changes</a></h1>
<p>Emu48+ is a modified version of Emu48 to add support for the ARM-based
calculators. It does not emulate the ARM CPU, but it enhances the
Saturn emulation to more closely match the emulation provided by the
Saturn emulator on the ARM-based calculators.</p>
<p>Emu48+ adds support for many of the Saturn+ instructions, including
some of the BUSCC instructions, and it also adds support for the 80-line
display used on the 49g+ and 50g.</p>
<p>At present, the additional calculators supported in Emu48+ are the
49g+, 48gII (hardware revision 1), 50g, and 39g+/39gs/40gs.</p>
<p>To create KML scripts for the additional calculator models, use the
following model codes:</p>
<table border="0" cellpadding="0" cellspacing="0" width="651" summary="DDE settings">
<tr>
<td width="111">39g+/39gs:</td>
<td width="536">Model "P"<br>
Class 39</td>
</tr>
<tr>
<td width="111">40gs:</td>
<td width="536">Model "P"<br>
Class 40</td>
</tr>
<tr>
<td width="111">48gII:</td>
<td width="536">Model "2"</td>
</tr>
<tr>
<td width="111">49g+:</td>
<td width="536">Model "Q"</td>
</tr>
<tr>
<td width="111">50g:</td>
<td width="536">Model "Q"<br>
Class 50</td>
</tr>
</table>
<p>Most of the code that was changed in Emu48+ over Emu48 was provided by
Cyrille de Brebisson of Hewlett-Packard.</p>
<h1><a name=s15>15. License</a></h1>
<h1><a name=s14>14. License</a></h1>
<p>Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator<br>
Copyright (C) 2017 Christoph Gie&szlig;elink</p>
<p>Emu48+ - A 39g+/39gs/40gs/48gII/49g+/50g Emulator<br>
Copyright (C) 2017 Cyrille de Brebisson<br>
Additional changes by Bill Graves and Eric Rechlin</p>
Copyright (C) 2018 Christoph Gie&szlig;elink</p>
<p>This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)

View file

@ -1,10 +1,10 @@
Additional known bugs and restrictions of Emu48 V1.57+
Additional known bugs and restrictions of Emu48 V1.59+
------------------------------------------------------
- some display issues, such as when scrolling up, that were fixed in
regular Emu48 haven't yet been merged into Emu48+
Known bugs and restrictions of Emu48 V1.59
Known bugs and restrictions of Emu48 V1.61
------------------------------------------
- the following I/O bits aren't emulated (incomplete)
@ -53,4 +53,4 @@ Known bugs and restrictions of Emu48 V1.59
- quitting the emulator while programming the flash isn't allowed,
because the content of flash state machine isn't saved so far
08/15/17 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
08/14/18 (c) by Christoph Gießelink, c dot giesselink at gmx dot de

View file

@ -1,4 +1,4 @@
Service Pack 57+ based on Emu48 Service Pack 59
Service Pack 59+ based on Emu48 Service Pack 61
See CHANGES.TXT in Emu48 for full history.
Only changes specifically made to Emu48+ are shown below.

View file

@ -348,7 +348,7 @@ VOID UpdateMainDisplay(VOID)
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
// CdB for HP: add 64/80 line display for apples
StretchBlt(hWindowDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom, 131*nLcdZoom, MAINSCREENHEIGHT*nLcdZoom,
StretchBlt(hWindowDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom, 131*nLcdZoom*nGdiXZoom, MAINSCREENHEIGHT*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.boffset, Chipset.d0size, 131, MAINSCREENHEIGHT, SRCCOPY);
GdiFlush();
}
@ -392,8 +392,8 @@ VOID UpdateMenuDisplay(VOID)
{
// CdB for HP: add 64/80 line display for apples
StretchBlt(hWindowDC,
nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom,
131*nLcdZoom, MENUHEIGHT*nLcdZoom,
nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
hLcdDC,
0, (MAINSCREENHEIGHT+Chipset.d0size),
131, MENUHEIGHT,
@ -497,8 +497,8 @@ VOID WriteToMainDisplay(LPBYTE a, DWORD d, UINT s)
if (y==y0) y++;
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom,
131*nLcdZoom, (y-y0)*nLcdZoom,
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.boffset, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
GdiFlush();
}
@ -554,8 +554,8 @@ VOID WriteToMenuDisplay(LPBYTE a, DWORD d, UINT s)
if (y==y0) y++;
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom,
131*nLcdZoom, (y-y0)*nLcdZoom,
StretchBlt(hWindowDC, nLcdX, nLcdY+y0*nLcdZoom*nGdiYZoom,
(131*nLcdZoom)*nGdiXZoom, (y-y0)*nLcdZoom*nGdiYZoom,
hLcdDC, 0, y0, 131, y-y0, SRCCOPY); // CdB for HP: add 64/80 line display for apples
GdiFlush();
}

View file

@ -266,7 +266,11 @@ static BOOL DoHexStream(DWORD *pdwAddr,String *str,UINT *pnLevel)
}
dwLength -= 5; // no. of DOCODE nibbles
PutFS(str,_T("%X "),dwLength); // write length information
PutFS(str,_T("%X"),dwLength); // write length information
if (dwLength > 0) // have data
{
PutC(str,_T(' '));
}
for (;dwLength > 0; --dwLength)
{
@ -328,9 +332,9 @@ static BOOL DoIntStream(DWORD *pdwAddr,String *str,UINT *pnLevel)
for (i = 0; i < dwLength; ++i) // read data
pbyData[i] = RplReadNibble(pdwAddr);
if (dwLength == 1) // special implementation for zero
if (dwLength <= 1) // special implementation for zero
{
_ASSERT(pbyData[0] == 0);
_ASSERT(dwLength == 0 || (dwLength == 1 && pbyData[0] == 0));
PutC(str,_T('0'));
}
else
@ -674,7 +678,11 @@ static BOOL DoHxs(DWORD *pdwAddr,String *str,UINT *pnLevel)
PutS(str,_T("HXS "));
dwLength -= 5; // no. of HXS
PutFS(str,_T("%X "),dwLength); // write length information
PutFS(str,_T("%X"),dwLength); // write length information
if (dwLength > 0) // have data
{
PutC(str,_T(' '));
}
bRemove = TRUE; // remove leading zeros

View file

@ -13,7 +13,7 @@
#include "kml.h"
#include "debugger.h"
#define VERSION "1.57+"
#define VERSION "1.59+"
#ifdef _DEBUG
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
@ -888,17 +888,17 @@ static LRESULT OnPaint(HWND hWindow)
// redraw header display area
StretchBlt(hPaintDC, nLcdX, nLcdY,
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.d0offset, 0, 131, Chipset.d0size, SRCCOPY);
hLcdDC, Chipset.d0offset, 0,
131, Chipset.d0size, SRCCOPY);
// redraw main display area
StretchBlt(hPaintDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.boffset, Chipset.d0size,
131, MAINSCREENHEIGHT, SRCCOPY);
131, nLines, SRCCOPY);
// redraw menu display area
StretchBlt(hPaintDC, nLcdX, nLcdY+(MAINSCREENHEIGHT+Chipset.d0size)*nLcdZoom*nGdiYZoom,
StretchBlt(hPaintDC, nLcdX, nLcdY+(nLines+Chipset.d0size)*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
hLcdDC, 0, (MAINSCREENHEIGHT+Chipset.d0size),
hLcdDC, 0, (nLines+Chipset.d0size),
131, MENUHEIGHT, SRCCOPY);
GdiFlush();
}
@ -1172,11 +1172,32 @@ static LRESULT OnViewCopy(VOID)
WORD wBits;
DWORD dwLen, dwSizeImage;
_ASSERT(nLcdZoom == 1 || nLcdZoom == 2 || nLcdZoom == 4);
hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdZoom,SCREENHEIGHT*nLcdZoom); // CdB for HP: add apples display stuff
_ASSERT(nLcdZoom >= 1 && nLcdZoom <= 4);
hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdZoom*nGdiXZoom,SCREENHEIGHT*nLcdZoom*nGdiYZoom); // CdB for HP: add apples display stuff
hBmpDC = CreateCompatibleDC(hLcdDC);
hBmp = (HBITMAP) SelectObject(hBmpDC,hBmp);
StretchBlt(hBmpDC,0,0,131*nLcdZoom,SCREENHEIGHT*nLcdZoom,hLcdDC,0,0, 131, SCREENHEIGHT, SRCCOPY); // CdB for HP: add apples display stuff
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
UINT nLines = MAINSCREENHEIGHT;
// copy header display area
StretchBlt(hBmpDC, 0, 0,
131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.d0offset, 0,
131, Chipset.d0size, SRCCOPY);
// copy main display area
StretchBlt(hBmpDC, 0, Chipset.d0size*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom,
hLcdDC, Chipset.boffset, Chipset.d0size,
131, nLines, SRCCOPY);
// copy menu display area
StretchBlt(hBmpDC, 0, (nLines+Chipset.d0size)*nLcdZoom*nGdiYZoom,
131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom,
hLcdDC, 0, (nLines+Chipset.d0size),
131, MENUHEIGHT, SRCCOPY);
GdiFlush();
}
LeaveCriticalSection(&csGDILock);
hBmp = (HBITMAP) SelectObject(hBmpDC,hBmp);
// fill BITMAP structure for size information

View file

@ -281,6 +281,12 @@ SOURCE=.\kml.c
# End Source File
# Begin Source File
SOURCE=.\lodepng.c
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP"
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=.\lowbat.c
# End Source File
# Begin Source File
@ -378,6 +384,10 @@ SOURCE=.\kml.h
# End Source File
# Begin Source File
SOURCE=.\lodepng.h
# End Source File
# Begin Source File
SOURCE=.\opcodes.h
# End Source File
# Begin Source File

View file

@ -295,7 +295,7 @@ FONT 8, "MS Sans Serif"
BEGIN
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE
LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP
LTEXT "Copyright © 2017 Christoph Gießelink && Sébastien Carlier",
LTEXT "Copyright © 2018 Christoph Gießelink && Sébastien Carlier",
IDC_STATIC,29,18,181,8
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
@ -691,8 +691,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,5,7,0
PRODUCTVERSION 1,5,7,0
FILEVERSION 1,5,9,0
PRODUCTVERSION 1,5,9,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -709,12 +709,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0"
VALUE "FileDescription", "HP38/39/40/48/49/50 Emulator\0"
VALUE "FileVersion", "1, 5, 7, 0\0"
VALUE "FileVersion", "1, 5, 9, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2017\0"
VALUE "LegalCopyright", "Copyright © 2018\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 5, 7, 0\0"
VALUE "ProductVersion", "1, 5, 9, 0\0"
END
END
BLOCK "VarFileInfo"

View file

@ -168,6 +168,12 @@ SOURCE=.\kml.c
# End Source File
# Begin Source File
SOURCE=.\lodepng.c
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP"
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=.\lowbat.c
# End Source File
# Begin Source File
@ -265,6 +271,10 @@ SOURCE=.\kml.h
# End Source File
# Begin Source File
SOURCE=.\lodepng.h
# End Source File
# Begin Source File
SOURCE=.\opcodes.h
# End Source File
# Begin Source File

View file

@ -13,6 +13,7 @@
#include "kml.h"
#include "i28f160.h" // flash support
#include "debugger.h"
#include "lodepng.h"
#pragma intrinsic(abs,labs)
@ -1935,7 +1936,7 @@ static HBITMAP DecodeGif(LPBMPFILE pBmp,DWORD *pdwTransparentColor)
// allocate buffer for pixels
VERIFY(hBitmap = CreateDIBSection(hWindowDC,
(LPBITMAPINFO)&bmi,
&bmi,
DIB_RGB_COLORS,
(VOID **)&pbyPixels,
NULL,
@ -2331,6 +2332,91 @@ quit:
return hBitmap;
}
static HBITMAP DecodePng(LPBMPFILE pBmp)
{
// this implementation use the PNG image file decoder
// engine of Copyright (c) 2005-2018 Lode Vandevenne
HBITMAP hBitmap;
UINT uError,uWidth,uHeight;
INT nWidth,nHeight;
LONG lBytesPerLine;
LPBYTE pbyImage; // PNG RGB image data
LPBYTE pbySrc; // source buffer pointer
LPBYTE pbyPixels; // BMP buffer
BITMAPINFO bmi;
hBitmap = NULL;
pbyImage = NULL;
// decode PNG image
uError = lodepng_decode_memory(&pbyImage,&uWidth,&uHeight,pBmp->pbyFile,pBmp->dwFileSize,LCT_RGB,8);
if (uError) goto quit;
ZeroMemory(&bmi,sizeof(bmi)); // init bitmap info
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = (LONG) uWidth;
bmi.bmiHeader.biHeight = (LONG) uHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24; // create a true color DIB
bmi.bmiHeader.biCompression = BI_RGB;
// bitmap dimensions
lBytesPerLine = WIDTHBYTES(bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount);
bmi.bmiHeader.biSizeImage = lBytesPerLine * bmi.bmiHeader.biHeight;
// allocate buffer for pixels
VERIFY(hBitmap = CreateDIBSection(hWindowDC,
&bmi,
DIB_RGB_COLORS,
(VOID **)&pbyPixels,
NULL,
0));
if (hBitmap == NULL) goto quit;
pbySrc = pbyImage; // init source loop pointer
// fill bottom up DIB pixel buffer with color information
for (nHeight = bmi.bmiHeader.biHeight - 1; nHeight >= 0; --nHeight)
{
LPBYTE pbyLine = pbyPixels + nHeight * lBytesPerLine;
for (nWidth = 0; nWidth < bmi.bmiHeader.biWidth; ++nWidth)
{
*pbyLine++ = pbySrc[2]; // blue
*pbyLine++ = pbySrc[1]; // green
*pbyLine++ = pbySrc[0]; // red
pbySrc += 3;
}
_ASSERT((DWORD) (pbyLine - pbyPixels) <= bmi.bmiHeader.biSizeImage);
}
if (hPalette == NULL)
{
hPalette = CreateBIPalette((PBITMAPINFOHEADER) &bmi);
// save old palette
hOldPalette = SelectPalette(hWindowDC, hPalette, FALSE);
RealizePalette(hWindowDC);
}
quit:
if (pbyImage != NULL) // buffer for PNG image allocated
{
free(pbyImage); // free PNG image data
}
if (hBitmap != NULL && uError != 0) // creation failed
{
DeleteObject(hBitmap); // delete bitmap
hBitmap = NULL;
}
return hBitmap;
}
HBITMAP LoadBitmapFile(LPCTSTR szFilename)
{
HANDLE hFile;
@ -2374,6 +2460,13 @@ HBITMAP LoadBitmapFile(LPCTSTR szFilename)
break;
}
// check for PNG file header
if (Bmp.dwFileSize >= 8 && memcmp(Bmp.pbyFile,"\x89PNG\r\n\x1a\n",8) == 0)
{
hBitmap = DecodePng(&Bmp);
break;
}
// unknown file type
hBitmap = NULL;
}
@ -2420,15 +2513,41 @@ static BOOL LabColorCmp(DWORD dwColor1,DWORD dwColor2,DWORD dwTol)
return dwDiff > dwTol; // FALSE = colors match
}
static DWORD EncodeColorBits(DWORD dwColorVal,DWORD dwMask)
{
#define MAXBIT 32
UINT uLshift = MAXBIT;
UINT uRshift = 8;
DWORD dwBitMask = dwMask;
dwColorVal &= 0xFF; // the color component using the lowest 8 bit
// position of highest bit
while ((dwBitMask & (1<<(MAXBIT-1))) == 0 && uLshift > 0)
{
dwBitMask <<= 1; // next bit
--uLshift; // next position
}
if (uLshift > 24) // avoid overflow on 32bit mask
{
uLshift -= uRshift; // normalize left shift
uRshift = 0;
}
return ((dwColorVal << uLshift) >> uRshift) & dwMask;
#undef MAXBIT
}
HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
{
#define ADD_RECTS_COUNT 256
BOOL (*fnColorCmp)(DWORD dwColor1,DWORD dwColor2,DWORD dwTol);
DWORD dwRed,dwGreen,dwBlue;
HRGN hRgn;
LPRGNDATA pRgnData;
BITMAP bm;
LPBITMAPINFO bi;
LPBYTE pbyBits;
LPBYTE pbyColor;
@ -2438,7 +2557,6 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
LONG x,y,xleft;
BOOL bFoundLeft;
BOOL bIsMask;
HDC hDC;
if (dwTol >= 1000) // use CIE L*a*b compare
{
@ -2450,16 +2568,13 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
fnColorCmp = AbsColorCmp;
}
// get image properties
GetObject(hBmp,sizeof(bm),&bm);
// allocate memory for extended image information incl. RGBQUAD color table
bi = (LPBITMAPINFO) calloc(1,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
_ASSERT(bi->bmiHeader.biBitCount == 0); // for query without color table
// get information about image
hDC = CreateCompatibleDC(hWindowDC);
GetDIBits(hDC,hBmp,0,bm.bmHeight,NULL,bi,DIB_RGB_COLORS);
GetDIBits(hWindowDC,hBmp,0,0,NULL,bi,DIB_RGB_COLORS);
// DWORD aligned bitmap width in BYTES
dwAlignedWidthBytes = WIDTHBYTES( bi->bmiHeader.biWidth
@ -2476,24 +2591,36 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
pbyBits = (LPBYTE) malloc(bi->bmiHeader.biSizeImage);
// fill bits buffer
GetDIBits(hDC,hBmp,0,bi->bmiHeader.biHeight,pbyBits,bi,DIB_RGB_COLORS);
DeleteDC(hDC);
GetDIBits(hWindowDC,hBmp,0,bi->bmiHeader.biHeight,pbyBits,bi,DIB_RGB_COLORS);
// convert color if current DC is 16-bit/32-bit bitfield coded
if (bi->bmiHeader.biCompression == BI_BITFIELDS)
{
dwRed = *(LPDWORD) &bi->bmiColors[0];
dwGreen = *(LPDWORD) &bi->bmiColors[1];
dwBlue = *(LPDWORD) &bi->bmiColors[2];
}
else // RGB coded
{
// convert color if current DC is 16-bit RGB coded
if (bi->bmiHeader.biBitCount == 16)
{
// for 15 bit (5:5:5)
color = ((color & 0xF80000) >> 19)
| ((color & 0x00F800) >> 6)
| ((color & 0x0000F8) << 7);
dwRed = 0x00007C00;
dwGreen = 0x000003E0;
dwBlue = 0x0000001F;
}
else
{
// convert COLORREF to RGBQUAD color
color = ((color & 0xFF0000) >> 16)
| ((color & 0x00FF00) >> 0)
| ((color & 0x0000FF) << 16);
dwRed = 0x00FF0000;
dwGreen = 0x0000FF00;
dwBlue = 0x000000FF;
}
}
color = EncodeColorBits((color >> 16), dwBlue)
| EncodeColorBits((color >> 8), dwGreen)
| EncodeColorBits((color >> 0), dwRed);
dwBpp = bi->bmiHeader.biBitCount >> 3; // bytes per pixel

View file

@ -1813,39 +1813,59 @@ static UINT iSqrt(UINT nNumber) // integer y=sqrt(x) function
return b;
}
static VOID AdjustPixel(UINT x, UINT y, BYTE byOffset)
static VOID AdjustPixel(LPBYTE pbyPixel, BYTE byOffset)
{
COLORREF rgb;
WORD wB, wG, wR;
INT i = 3; // BGR colors
rgb = GetPixel(hWindowDC, x, y);
// adjust color red
wR = (((WORD) rgb) & 0x00FF) + byOffset;
if (wR > 0xFF) wR = 0xFF;
rgb >>= 8;
// adjust color green
wG = (((WORD) rgb) & 0x00FF) + byOffset;
if (wG > 0xFF) wG = 0xFF;
rgb >>= 8;
// adjust color blue
wB = (((WORD) rgb) & 0x00FF) + byOffset;
if (wB > 0xFF) wB = 0xFF;
SetPixel(hWindowDC, x, y, RGB(wR,wG,wB));
while (--i >= 0)
{
WORD wColor = (WORD) *pbyPixel + byOffset;
// jumpless saturation to 0xFF
wColor = -(wColor >> 8) | (BYTE) wColor;
*pbyPixel++ = (BYTE) wColor;
}
return;
}
// draw transparent circle with center coordinates and radius in pixel
static __inline VOID TransparentCircle(UINT cx, UINT cy, UINT r)
// draw transparent circle button type
static __inline VOID TransparentCircle(UINT nOx, UINT nOy, UINT nCx, UINT nCy)
{
#define HIGHADJ 0x80 // color incr. at center
#define LOWADJ 0x10 // color incr. at border
UINT x, y, rr, rrc;
BITMAPINFO bmi;
HDC hMemDC;
HBITMAP hMemBitMap;
LPBYTE pbyPixels; // BMP data
UINT x, y, cx, cy, r, rr, rrc;
r = min(nCx,nCy) / 2; // radius
if (r < 2) return; // radius 2 pixel minimum
// create memory copy of button rectangle
ZeroMemory(&bmi,sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = (LONG) nCx;
bmi.bmiHeader.biHeight = (LONG) nCy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32; // use 32 bit bitmap for easier buffer calculation
bmi.bmiHeader.biCompression = BI_RGB;
VERIFY(hMemBitMap = CreateDIBSection(hWindowDC,
&bmi,
DIB_RGB_COLORS,
(VOID **)&pbyPixels,
NULL,
0));
if (hMemBitMap == NULL) return;
hMemDC = CreateCompatibleDC(hWindowDC);
hMemBitMap = (HBITMAP) SelectObject(hMemDC,hMemBitMap);
BitBlt(hMemDC, 0, 0, nCx, nCy, hWindowDC, nOx, nOy, SRCCOPY);
cx = nCx / 2; // x-center coordinate
cy = nCy / 2; // y-center coordinate
rr = r * r; // calculate r^2
rrc = (r-1) * (r-1); // calculate (r-1)^2 for color steps
@ -1862,12 +1882,31 @@ static __inline VOID TransparentCircle(UINT cx, UINT cy, UINT r)
// color offset, sqrt(x*x+y*y) < r !!!
BYTE byOff = HIGHADJ - (BYTE) (iSqrt((x*x+yy) * (HIGHADJ-LOWADJ)*(HIGHADJ-LOWADJ) / rrc));
AdjustPixel(cx+x, cy+y, byOff);
if (x != 0) AdjustPixel(cx-x, cy+y, byOff);
if (y != 0) AdjustPixel(cx+x, cy-y, byOff);
if (x != 0 && y != 0) AdjustPixel(cx-x, cy-y, byOff);
AdjustPixel(pbyPixels + (((cy+y) * bmi.bmiHeader.biWidth + (cx+x)) << 2), byOff);
if (x != 0)
{
AdjustPixel(pbyPixels + (((cy+y) * bmi.bmiHeader.biWidth + (cx-x)) << 2), byOff);
}
if (y != 0)
{
AdjustPixel(pbyPixels + (((cy-y) * bmi.bmiHeader.biWidth + (cx+x)) << 2), byOff);
}
if (x != 0 && y != 0)
{
AdjustPixel(pbyPixels + (((cy-y) * bmi.bmiHeader.biWidth + (cx-x)) << 2), byOff);
}
}
}
// update button area with modified data
BitBlt(hWindowDC, nOx, nOy, nCx, nCy, hMemDC, 0, 0, SRCCOPY);
// delete memory bitmap
VERIFY(DeleteObject(SelectObject(hMemDC,hMemBitMap)));
DeleteDC(hMemDC);
return;
#undef HIGHADJ
@ -1948,9 +1987,7 @@ static VOID DrawButton(UINT nId)
case 5: // transparent circle
if (pButton[nId].bDown)
{
TransparentCircle(x0 + pButton[nId].nCx / 2, // x-center coordinate
y0 + pButton[nId].nCy / 2, // y-center coordinate
min(pButton[nId].nCx,pButton[nId].nCy) / 2); // radius
TransparentCircle(x0, y0, pButton[nId].nCx, pButton[nId].nCy);
}
else
{

6300
source/LODEPNG.C Normal file

File diff suppressed because it is too large Load diff

1770
source/LODEPNG.H Normal file

File diff suppressed because it is too large Load diff