2018-09-09: Updated to version 59
Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
parent
d048b845e4
commit
311f1aa6b5
15 changed files with 8379 additions and 139 deletions
BIN
Emu48.dll
BIN
Emu48.dll
Binary file not shown.
BIN
Emu48.exe
BIN
Emu48.exe
Binary file not shown.
55
Emu48.htm
55
Emu48.htm
|
@ -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ß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ß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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
191
source/FILES.C
191
source/FILES.C
|
@ -13,6 +13,7 @@
|
|||
#include "kml.h"
|
||||
#include "i28f160.h" // flash support
|
||||
#include "debugger.h"
|
||||
#include "lodepng.h"
|
||||
|
||||
#pragma intrinsic(abs,labs)
|
||||
|
||||
|
@ -101,7 +102,7 @@ VOID SetWindowLocation(HWND hWnd,INT nPosX,INT nPosY)
|
|||
|
||||
DWORD GetCutPathName(LPCTSTR szFileName, LPTSTR szBuffer, DWORD dwBufferLength, INT nCutLength)
|
||||
{
|
||||
TCHAR cPath[_MAX_PATH]; // full filename
|
||||
TCHAR cPath[_MAX_PATH]; // full filename
|
||||
TCHAR cDrive[_MAX_DRIVE];
|
||||
TCHAR cDir[_MAX_DIR];
|
||||
TCHAR cFname[_MAX_FNAME];
|
||||
|
@ -112,9 +113,9 @@ DWORD GetCutPathName(LPCTSTR szFileName, LPTSTR szBuffer, DWORD dwBufferLength,
|
|||
// split original filename into parts
|
||||
_tsplitpath(szFileName,cDrive,cDir,cFname,cExt);
|
||||
|
||||
if (*cDir != 0) // contain directory part
|
||||
if (*cDir != 0) // contain directory part
|
||||
{
|
||||
LPTSTR lpFilePart; // address of file name in path
|
||||
LPTSTR lpFilePart; // address of file name in path
|
||||
INT nNameLen,nPathLen,nMaxPathLen;
|
||||
|
||||
GetFullPathName(szFileName,ARRAYSIZEOF(cPath),cPath,&lpFilePart);
|
||||
|
@ -1480,8 +1481,8 @@ BOOL GetSaveObjectFilename(LPCTSTR lpstrFilter,LPCTSTR lpstrDefExt)
|
|||
|
||||
WORD WriteStack(UINT nStkLevel,LPBYTE lpBuf,DWORD dwSize) // separated from LoadObject()
|
||||
{
|
||||
BOOL bBinary;
|
||||
DWORD dwAddress, i;
|
||||
BOOL bBinary;
|
||||
DWORD dwAddress, i;
|
||||
|
||||
bBinary = ((lpBuf[dwSize+0]=='H')
|
||||
&& (lpBuf[dwSize+1]=='P')
|
||||
|
@ -1568,11 +1569,11 @@ BOOL LoadObject(LPCTSTR szFilename) // separated stack writing part
|
|||
|
||||
BOOL SaveObject(LPCTSTR szFilename) // separated stack reading part
|
||||
{
|
||||
HANDLE hFile;
|
||||
LPBYTE pbyHeader;
|
||||
DWORD lBytesWritten;
|
||||
DWORD dwAddress;
|
||||
DWORD dwLength;
|
||||
HANDLE hFile;
|
||||
LPBYTE pbyHeader;
|
||||
DWORD lBytesWritten;
|
||||
DWORD dwAddress;
|
||||
DWORD dwLength;
|
||||
|
||||
dwAddress = RPL_Pick(1);
|
||||
if (dwAddress == 0)
|
||||
|
@ -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 RGB coded
|
||||
if (bi->bmiHeader.biBitCount == 16)
|
||||
// convert color if current DC is 16-bit/32-bit bitfield coded
|
||||
if (bi->bmiHeader.biCompression == BI_BITFIELDS)
|
||||
{
|
||||
// for 15 bit (5:5:5)
|
||||
color = ((color & 0xF80000) >> 19)
|
||||
| ((color & 0x00F800) >> 6)
|
||||
| ((color & 0x0000F8) << 7);
|
||||
dwRed = *(LPDWORD) &bi->bmiColors[0];
|
||||
dwGreen = *(LPDWORD) &bi->bmiColors[1];
|
||||
dwBlue = *(LPDWORD) &bi->bmiColors[2];
|
||||
}
|
||||
else
|
||||
else // RGB coded
|
||||
{
|
||||
// convert COLORREF to RGBQUAD color
|
||||
color = ((color & 0xFF0000) >> 16)
|
||||
| ((color & 0x00FF00) >> 0)
|
||||
| ((color & 0x0000FF) << 16);
|
||||
// convert color if current DC is 16-bit RGB coded
|
||||
if (bi->bmiHeader.biBitCount == 16)
|
||||
{
|
||||
// for 15 bit (5:5:5)
|
||||
dwRed = 0x00007C00;
|
||||
dwGreen = 0x000003E0;
|
||||
dwBlue = 0x0000001F;
|
||||
}
|
||||
else
|
||||
{
|
||||
// convert COLORREF to RGBQUAD color
|
||||
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
|
||||
|
||||
|
@ -2537,7 +2664,7 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
|
|||
}
|
||||
pbyColor += dwBpp; // shift pointer to next color
|
||||
|
||||
if (!bFoundLeft && bIsMask) // non transparent color found
|
||||
if (!bFoundLeft && bIsMask) // non transparent color found
|
||||
{
|
||||
xleft = x;
|
||||
bFoundLeft = TRUE;
|
||||
|
|
93
source/KML.C
93
source/KML.C
|
@ -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
6300
source/LODEPNG.C
Normal file
File diff suppressed because it is too large
Load diff
1770
source/LODEPNG.H
Normal file
1770
source/LODEPNG.H
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue