2023-09-17: Updated to version 65

Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
Gwenhael Le Moine 2024-03-20 07:46:29 +01:00
parent 0218951158
commit 11a3dc67ce
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
20 changed files with 1235 additions and 382 deletions

BIN
Emu48.dll

Binary file not shown.

BIN
Emu48.exe

Binary file not shown.

View file

@ -16,8 +16,6 @@
#define w Chipset
#define _KB(s) ((s) * 1024 * 2)
#pragma intrinsic(memset,memcpy)
#include "Ops.h"
@ -55,7 +53,7 @@ static CONST LPBYTE ppReg[] = { w.A, w.B, w.C, w.D };
static QWORD DecodeReg64(LPBYTE R, BYTE byNF)
{
QWORD qwVal = Npack64(R,16); // generate 64bit number from register
switch (byNF) // field selector
{
case 0: return (qwVal >> (w.P*4)) & 0xf; // P
@ -324,7 +322,7 @@ _ASSERT(FALSE); // not tested so far
// clear bank
EraseBlock(dwStart,dwStop-dwStart);
w.carry = FALSE; // no error
return;
}
@ -396,7 +394,7 @@ VOID o80BExt(LPBYTE I) // Saturnator extentions
case 0x0A: break; // KEYDN not implemented
case 0x0B: break; // no doslow implemented
case 0x10: // simulate off function
{
{
BOOL bShutdn = TRUE; // shut down
// only shut down when no timer wake up

View file

@ -29,31 +29,36 @@ typedef struct
static VOID PutSn(String *str, LPCTSTR szVal, DWORD dwLen)
{
if (str != NULL) // with output
if (str != NULL && dwLen > 0) // with output and actual string length
{
if (str->dwSize == 0) // no buffer allocated
// string buffer to small
if (str->dwPos + dwLen > str->dwSize)
{
str->dwSize = ALLOCSIZE; // buffer size
VERIFY(str->szBuffer = (LPTSTR) malloc(str->dwSize * sizeof(TCHAR)));
str->dwPos = 0;
LPTSTR szNewBuffer;
DWORD dwMinSize;
dwMinSize = dwLen + str->dwSize - str->dwPos;
dwMinSize = (dwMinSize + ALLOCSIZE - 1) / ALLOCSIZE;
dwMinSize *= ALLOCSIZE;
str->dwSize += dwMinSize; // new buffer size
VERIFY(szNewBuffer = (LPTSTR) realloc(str->szBuffer,str->dwSize * sizeof(TCHAR)));
if (szNewBuffer) // new buffer allocated
{
str->szBuffer = szNewBuffer;
}
else // allocation failed
{
str->dwSize = 0; // size of buffer
free(str->szBuffer); // buffer memory
str->szBuffer = NULL;
str->dwPos = 0; // position inside buffer
}
}
_ASSERT(str->szBuffer != NULL);
if (dwLen > 0) // actual string length
if (str->szBuffer)
{
// string buffer to small
if (str->dwPos + dwLen > str->dwSize)
{
DWORD dwMinSize;
dwMinSize = dwLen + str->dwSize - str->dwPos;
dwMinSize = (dwMinSize + ALLOCSIZE - 1) / ALLOCSIZE;
dwMinSize *= ALLOCSIZE;
str->dwSize += dwMinSize; // new buffer size
VERIFY(str->szBuffer = (LPTSTR) realloc(str->szBuffer,str->dwSize * sizeof(TCHAR)));
}
CopyMemory(&str->szBuffer[str->dwPos],szVal,dwLen * sizeof(TCHAR));
str->dwPos += dwLen;
}
@ -212,23 +217,24 @@ static BOOL BCDx(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,String *str)
static BOOL BINx(DWORD *pdwAddr,INT nBinLen,String *str)
{
LPBYTE pbyNumber;
INT i;
VERIFY(pbyNumber = (LPBYTE) malloc(nBinLen));
for (i = 0; i < nBinLen; ++i) // read data
pbyNumber[i] = RplReadNibble(pdwAddr);
// strip leading zeros
for (i = nBinLen - 1; pbyNumber[i] == 0 && i > 0; --i) { }
for (; i >= 0; --i) // write rest of bin
LPBYTE pbyNumber = (LPBYTE) malloc(nBinLen);
if (pbyNumber != NULL)
{
PutC(str,cHex[pbyNumber[i]]);
}
INT i;
free(pbyNumber);
for (i = 0; i < nBinLen; ++i) // read data
pbyNumber[i] = RplReadNibble(pdwAddr);
// strip leading zeros
for (i = nBinLen - 1; pbyNumber[i] == 0 && i > 0; --i) { }
for (; i >= 0; --i) // write rest of bin
{
PutC(str,cHex[pbyNumber[i]]);
}
free(pbyNumber);
}
return FALSE;
}
@ -327,29 +333,31 @@ static BOOL DoIntStream(DWORD *pdwAddr,String *str,UINT *pnLevel)
dwLength -= 5; // object length
VERIFY(pbyData = (LPBYTE) malloc(dwLength));
for (i = 0; i < dwLength; ++i) // read data
pbyData[i] = RplReadNibble(pdwAddr);
if (dwLength <= 1) // special implementation for zero
pbyData = (LPBYTE) malloc(dwLength);
if (pbyData != NULL)
{
_ASSERT(dwLength == 0 || (dwLength == 1 && pbyData[0] == 0));
PutC(str,_T('0'));
}
else
{
if (pbyData[--dwLength] == 9) // negative number
PutC(str,_T('-'));
for (i = 0; i < dwLength; ++i) // read data
pbyData[i] = RplReadNibble(pdwAddr);
while (dwLength > 0) // write rest of zint
if (dwLength <= 1) // special implementation for zero
{
// use only decimal part for translation
PutC(str,cHex[pbyData[--dwLength]]);
_ASSERT(dwLength == 0 || (dwLength == 1 && pbyData[0] == 0));
PutC(str,_T('0'));
}
}
else
{
if (pbyData[--dwLength] == 9) // negative number
PutC(str,_T('-'));
free(pbyData);
while (dwLength > 0) // write rest of zint
{
// use only decimal part for translation
PutC(str,cHex[pbyData[--dwLength]]);
}
}
free(pbyData);
}
return FALSE;
UNREFERENCED_PARAMETER(pnLevel);
}
@ -1291,9 +1299,9 @@ DWORD RplSkipObject(DWORD dwAddr)
LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr)
{
String str = { 0 };
DWORD dwNxtAddr;
UINT nLevel = 0; // don't nest DOCOL objects
String str = { 0, NULL, 0 };
DWORD dwNxtAddr;
UINT nLevel = 0; // don't nest DOCOL objects
dwNxtAddr = dwAddr; // init next address
@ -1302,7 +1310,7 @@ LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr)
PutC(&str,0); // set EOS
// release unnecessary allocated buffer memory
// release unnecessary allocated buffer memory (shrinking)
VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0])));
// return address of next object
@ -1472,7 +1480,7 @@ static DWORD AssemblyOutput(DWORD dwAddr, DWORD dwEndAddr, DWORD dwLevel, String
LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
{
String str = { 0 };
String str = { 0, NULL, 0 };
LPCTSTR lpszName;
LPTSTR lpszObject;
DWORD dwLevel,dwAddr,dwNxtAddr;
@ -1486,6 +1494,10 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
for (dwAddr = dwStartAddr;dwAddr < dwEndAddr; dwAddr = dwNxtAddr)
{
lpszObject = RplDecodeObject(dwAddr,&dwNxtAddr);
if (lpszObject == NULL) // no memory
{
break; // break decoding
}
if (dwLevel > 0 && lstrcmp(lpszObject,_T(";")) == 0)
--dwLevel;
@ -1586,7 +1598,7 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
PutC(&str,0); // set EOS
// release unnecessary allocated buffer memory
// release unnecessary allocated buffer memory (shrinking)
VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0])));
return str.szBuffer;
}

View file

@ -13,7 +13,7 @@
#include "kml.h"
#include "debugger.h"
#define VERSION "1.64+"
#define VERSION "1.65+"
#ifdef _DEBUG
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
@ -2042,19 +2042,19 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
typedef DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
MSG msg;
WNDCLASS wc;
ATOM classAtom;
RECT rectWindow;
HACCEL hAccel;
DWORD dwThreadId;
LPFN_STIP fnSetThreadIdealProcessor;
DWORD dwProcessor;
HSZ hszService, hszTopic; // variables for DDE server
LPTSTR lpFilePart;
// module handle to kernel32
const HMODULE hmKernel32 = GetModuleHandle(_T("kernel32"));
// enable memory leak detection
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
@ -2147,6 +2147,26 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
return 0; // quit program
}
// disable TIMER_RESOLUTION throttling for Windows 11 and later
{
typedef const BOOL(WINAPI* LPFN_SPI)(HANDLE hProcess,INT ProcessInformationClass,LPVOID ProcessInformation,DWORD ProcessInformationSize);
// SetProcessInformation() is available since Windows 8, PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION since Windows 11
LPFN_SPI fnSetProcessInformation = (LPFN_SPI) GetProcAddress(hmKernel32, "SetProcessInformation");
if (fnSetProcessInformation != NULL) // running on Windows 8 or later
{
PROCESS_POWER_THROTTLING_STATE Ppts;
ZeroMemory(&Ppts,sizeof(Ppts));
Ppts.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
Ppts.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
// don't check for success, success only on Windoes 11 and later
fnSetProcessInformation(GetCurrentProcess(),ProcessPowerThrottling,&Ppts,sizeof(Ppts));
}
}
// Create window
rectWindow.left = 0;
rectWindow.top = 0;
@ -2197,15 +2217,29 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
return FALSE;
}
// SetThreadIdealProcessor() is available since Windows NT4.0
fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(GetModuleHandle(_T("kernel32")),
"SetThreadIdealProcessor");
// get processor for Saturn CPU thread
{
// GetCurrentProcessorNumber() is available since Windows Vista
typedef const DWORD (WINAPI *LPFN_GCPN)(VOID);
LPFN_GCPN fnGetCurrentProcessorNumber = (LPFN_GCPN) GetProcAddress(hmKernel32,"GetCurrentProcessorNumber");
// bind Saturn CPU emulation thread to current ideal processor
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no.
: 0; // select 1st processor
if (fnGetCurrentProcessorNumber != NULL) // running on Vista or later
{
dwProcessor = fnGetCurrentProcessorNumber(); // get current processor number
}
else
{
// SetThreadIdealProcessor() is available since Windows NT4.0
typedef const DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
LPFN_STIP fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(hmKernel32,"SetThreadIdealProcessor");
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no.
: 0; // select 1st processor
}
}
// bind Saturn CPU emulation thread to selected processor
// on multiprocessor machines for QueryPerformanceCounter()
VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor)));
ResumeThread(hThread); // start thread

View file

@ -278,7 +278,7 @@ SOURCE=.\kml.c
# Begin Source File
SOURCE=.\lodepng.c
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP"
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP" /D "LODEPNG_NO_COMPILE_CRC"
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
@ -304,10 +304,18 @@ SOURCE=.\pch.c
# End Source File
# Begin Source File
SOURCE=.\pngcrc.c
# End Source File
# Begin Source File
SOURCE=.\redeye.c
# End Source File
# Begin Source File
SOURCE=.\romcrc.c
# End Source File
# Begin Source File
SOURCE=.\rpl.c
# End Source File
# Begin Source File

View file

@ -8,6 +8,8 @@
*/
#include "types.h"
#define _KB(a) ((a)*2*1024)
#define HARDWARE "Yorke" // emulator hardware
#define MODELS "26AEGPQSX" // valid calculator models
#define APPLEHARD "2PQ" // Apple platform calculator models
@ -72,6 +74,9 @@ enum MMUMAP { M_IO, M_ROM, M_RAM, M_P1, M_P2, M_BS };
// values for disassembler memory mapping modes
enum MEM_MAPPING { MEM_MMU, MEM_NCE1, MEM_NCE2, MEM_CE1, MEM_CE2, MEM_NCE3 };
// Kermit CRC calculation
static __inline WORD UpCRC(WORD wCRC, BYTE nib) { return (wCRC >> 4) ^ (((wCRC ^ nib) & 0xf) * 0x1081); }
// Emu48.c
extern HPALETTE hPalette;
extern HPALETTE hOldPalette;
@ -254,6 +259,7 @@ extern DWORD dwRomSize;
extern LPBYTE pbyRomDirtyPage;
extern DWORD dwRomDirtyPageSize;
extern WORD wRomCrc;
extern BOOL bRomCrcCorrection;
extern LPBYTE pbyPort2;
extern BOOL bPort2Writeable;
extern BOOL bPort2IsShared;
@ -265,12 +271,12 @@ extern VOID SetWindowLocation(HWND hWnd,INT nPosX,INT nPosY);
extern DWORD GetCutPathName(LPCTSTR szFileName,LPTSTR szBuffer,DWORD dwBufferLength,INT nCutLength);
extern VOID SetWindowPathTitle(LPCTSTR szFileName);
extern BOOL CheckForBeepPatch(VOID);
extern BOOL PatchNibble(DWORD dwAddress, BYTE byPatch);
extern VOID UpdatePatches(BOOL bPatch);
extern BOOL PatchRom(LPCTSTR szFilename);
extern BOOL CrcRom(WORD *pwChk);
extern BOOL MapRom(LPCTSTR szFilename);
extern VOID UnmapRom(VOID);
extern BOOL CrcPort2(WORD *pwCrc);
extern BOOL MapPort2(LPCTSTR szFilename);
extern VOID UnmapPort2(VOID);
extern VOID ResetDocument(VOID);
@ -293,6 +299,9 @@ extern VOID LoadIconDefault(VOID);
extern HBITMAP LoadBitmapFile(LPCTSTR szFilename,BOOL bPalette);
extern HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol);
// Romcrc.c
extern VOID RebuildRomCrc(VOID);
// Timer.c
extern VOID SetHP48Time(VOID);
extern VOID StartTimers(VOID);

View file

@ -303,7 +303,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 © 2022 Christoph Gießelink && Sébastien Carlier",
LTEXT "Copyright © 2023 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 |
@ -723,8 +723,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,6,4,0
PRODUCTVERSION 1,6,4,0
FILEVERSION 1,6,5,0
PRODUCTVERSION 1,6,5,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -741,12 +741,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0"
VALUE "FileDescription", "HP38/39/40/48/49/50 Emulator\0"
VALUE "FileVersion", "1, 6, 4, 0\0"
VALUE "FileVersion", "1, 6, 5, 0\0"
VALUE "InternalName", "Emu48+\0"
VALUE "LegalCopyright", "Copyright © 2022\0"
VALUE "LegalCopyright", "Copyright © 2023\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48+\0"
VALUE "ProductVersion", "1, 6, 4, 0\0"
VALUE "ProductVersion", "1, 6, 5, 0\0"
END
END
BLOCK "VarFileInfo"

View file

@ -78,15 +78,15 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
//
BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name)
{
typedef DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
RECT rectWindow;
DWORD dwThreadId;
LPFN_STIP fnSetThreadIdealProcessor;
DWORD dwProcessor;
BOOL bFileExist = FALSE; // state file don't exist
// module handle to kernel32
const HMODULE hmKernel32 = GetModuleHandle(_T("kernel32"));
hApp = GetModuleHandle(_T("EMU48.DLL"));
if (hApp == NULL) return TRUE;
@ -113,6 +113,26 @@ BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name)
GetCurrentDirectory(ARRAYSIZEOF(szCurrentDirectory),szCurrentDirectory);
ReadSettings();
// disable TIMER_RESOLUTION throttling for Windows 11 and later
{
typedef const BOOL(WINAPI* LPFN_SPI)(HANDLE hProcess,INT ProcessInformationClass,LPVOID ProcessInformation,DWORD ProcessInformationSize);
// SetProcessInformation() is available since Windows 8, PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION since Windows 11
LPFN_SPI fnSetProcessInformation = (LPFN_SPI)GetProcAddress(hmKernel32, "SetProcessInformation");
if (fnSetProcessInformation != NULL) // running on Windows 8 or later
{
PROCESS_POWER_THROTTLING_STATE Ppts;
ZeroMemory(&Ppts,sizeof(Ppts));
Ppts.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
Ppts.ControlMask = PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
// don't check for success, success only on Windoes 11 and later
fnSetProcessInformation(GetCurrentProcess(),ProcessPowerThrottling,&Ppts,sizeof(Ppts));
}
}
// Create window
rectWindow.left = 0;
rectWindow.top = 0;
@ -174,15 +194,29 @@ BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name)
return TRUE;
}
// SetThreadIdealProcessor() is available since Windows NT4.0
fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(GetModuleHandle(_T("kernel32")),
"SetThreadIdealProcessor");
// get processor for Saturn CPU thread
{
// GetCurrentProcessorNumber() is available since Windows Vista
typedef const DWORD (WINAPI *LPFN_GCPN)(VOID);
LPFN_GCPN fnGetCurrentProcessorNumber = (LPFN_GCPN) GetProcAddress(hmKernel32,"GetCurrentProcessorNumber");
// bind Saturn CPU emulation thread to current ideal processor
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no.
: 0; // select 1st processor
if (fnGetCurrentProcessorNumber != NULL) // running on Vista or later
{
dwProcessor = fnGetCurrentProcessorNumber(); // get current processor number
}
else
{
// SetThreadIdealProcessor() is available since Windows NT4.0
typedef const DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
LPFN_STIP fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(hmKernel32,"SetThreadIdealProcessor");
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no.
: 0; // select 1st processor
}
}
// bind Saturn CPU emulation thread to selected processor
// on multiprocessor machines for QueryPerformanceCounter()
VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor)));
ResumeThread(hThread); // start thread

View file

@ -165,7 +165,7 @@ SOURCE=.\kml.c
# 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"
# ADD CPP /D "LODEPNG_NO_COMPILE_ENCODER" /D "LODEPNG_NO_COMPILE_DISK" /D "LODEPNG_NO_COMPILE_ERROR_TEXT" /D "LODEPNG_NO_COMPILE_CPP" /D "LODEPNG_NO_COMPILE_CRC"
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
@ -191,10 +191,18 @@ SOURCE=.\pch.c
# End Source File
# Begin Source File
SOURCE=.\pngcrc.c
# End Source File
# Begin Source File
SOURCE=.\redeye.c
# End Source File
# Begin Source File
SOURCE=.\romcrc.c
# End Source File
# Begin Source File
SOURCE=.\rpl.c
# End Source File
# Begin Source File

View file

@ -42,6 +42,7 @@ DWORD dwRomSize = 0;
LPBYTE pbyRomDirtyPage = NULL;
DWORD dwRomDirtyPageSize = 0;
WORD wRomCrc = 0; // fingerprint of patched ROM
BOOL bRomCrcCorrection = FALSE; // ROM CRC correction disabled
LPBYTE pbyPort2 = NULL;
BOOL bPort2Writeable = FALSE;
@ -53,18 +54,21 @@ WORD wPort2Crc = 0; // fingerprint of port2
BOOL bBackup = FALSE;
static HANDLE hRomFile = NULL;
static HANDLE hRomMap = NULL;
static HANDLE hPort2File = NULL;
static HANDLE hPort2Map = NULL;
// document signatures
static BYTE pbySignatureA[16] = "Emu38 Document\xFE";
static BYTE pbySignatureB[16] = "Emu39 Document\xFE";
static BYTE pbySignatureE[16] = "Emu48 Document\xFE";
static BYTE pbySignatureW[16] = "Win48 Document\xFE";
static BYTE pbySignatureV[16] = "Emu49 Document\xFE";
static HANDLE hCurrentFile = NULL;
// valid document signatures
static CONST LPBYTE bySignature[] =
{
(CONST LPBYTE) "Emu48 Document\xFE",
(CONST LPBYTE) "Emu38 Document\xFE",
(CONST LPBYTE) "Emu39 Document\xFE",
(CONST LPBYTE) "Emu49 Document\xFE",
(CONST LPBYTE) "Win48 Document\xFE",
(CONST LPBYTE) "Win48 Document\xFF"
};
static CHIPSET BackupChipset;
static LPBYTE BackupPort0;
static LPBYTE BackupPort1;
@ -102,11 +106,11 @@ 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 cDrive[_MAX_DRIVE];
TCHAR cDir[_MAX_DIR];
TCHAR cFname[_MAX_FNAME];
TCHAR cExt[_MAX_EXT];
TCHAR cPath[_MAX_PATH]; // full filename
TCHAR cDrive[_MAX_DRIVE];
TCHAR cDir[_MAX_DIR];
TCHAR cFname[_MAX_FNAME];
TCHAR cExt[_MAX_EXT];
_ASSERT(nCutLength >= 0); // 0 = only drive and name
@ -209,7 +213,7 @@ BOOL CheckForBeepPatch(VOID)
} BEEPPATCH, *PBEEPPATCH;
// known beep patches
const BEEPPATCH s38[] = { { 0x017D0, { 0x8, 0x1, 0xB, 0x1 } } };
const BEEPPATCH s38[] = { { 0x017D0, { 0x8, 0x1, 0xB, 0x1 } } };
const BEEPPATCH s39[] = { { 0x017BC, { 0x8, 0x1, 0xB, 0x1 } } };
const BEEPPATCH s48[] = { { 0x017A6, { 0x8, 0x1, 0xB, 0x1 } } };
const BEEPPATCH s49[] = { { 0x4157A, { 0x8, 0x1, 0xB, 0x1 } }, // 1.18/1.19-5/1.19-6
@ -289,7 +293,7 @@ typedef struct tnode
static TREENODE *nodePatch = NULL;
static BOOL PatchNibble(DWORD dwAddress, BYTE byPatch)
BOOL PatchNibble(DWORD dwAddress, BYTE byPatch)
{
PTREENODE p;
@ -446,6 +450,7 @@ BOOL PatchRom(LPCTSTR szFilename)
{
// patch ROM and save original nibble
PatchNibble(dwAddress, Asc2Nib(lpBuf[nPos]));
bRomCrcCorrection = TRUE;
}
++dwAddress;
}
@ -480,7 +485,7 @@ BOOL CrcRom(WORD *pwChk) // calculate fingerprint of ROM
// use checksum, because it's faster
while (dwSize-- > 0)
{
DWORD dwData = *pdwData++;
CONST DWORD dwData = *pdwData++;
if ((dwData & 0xF0F0F0F0) != 0) // data packed?
return FALSE;
dwChk += dwData;
@ -501,6 +506,7 @@ BOOL MapRom(LPCTSTR szFilename)
{
return FALSE;
}
bRomCrcCorrection = FALSE; // ROM CRC correction disabled
SetCurrentDirectory((*szRomDirectory == 0) ? szEmuDirectory : szRomDirectory);
if (bRomRW) // ROM writeable
{
@ -597,12 +603,13 @@ BOOL MapRom(LPCTSTR szFilename)
if (bRomPacked) // packed ROM image
{
dwSize = dwRomSize; // destination start address
while (dwFileSize > 0) // unpack source
LPBYTE pbySrc = pbyRom+dwFileSize; // source start address
LPBYTE pbyDest = pbyRom+dwRomSize; // destination start address
while (pbySrc != pbyDest) // unpack source
{
BYTE byValue = pbyRom[--dwFileSize];
pbyRom[--dwSize] = byValue >> 4;
pbyRom[--dwSize] = byValue & 0xF;
CONST BYTE byValue = *(--pbySrc);
*(--pbyDest) = byValue >> 4;
*(--pbyDest) = byValue & 0xF;
}
}
return TRUE;
@ -638,19 +645,19 @@ VOID UnmapRom(VOID)
if (bRomPacked) // repack data
{
LPBYTE pbySrc,pbyDest;
DWORD j;
LPBYTE pbySrc,pbyDest,pbyEnd;
dwSize /= 2; // adjust no. of bytes to write
dwFilePos /= 2; // linear pos in packed file
// pack data in page
pbySrc = pbyDest = &pbyRom[dwLinPos];
for (j = 0; j < dwSize; j++)
pbyEnd = pbyDest + dwSize;
while (pbyDest < pbyEnd)
{
*pbyDest = *pbySrc++;
*pbyDest |= *pbySrc++ << 4;
pbyDest++;
++pbyDest;
}
}
@ -670,6 +677,7 @@ VOID UnmapRom(VOID)
pbyRom = NULL;
dwRomSize = 0;
wRomCrc = 0;
bRomCrcCorrection = FALSE; // ROM CRC correction disabled
return;
}
@ -681,25 +689,24 @@ VOID UnmapRom(VOID)
//#
//################
BOOL CrcPort2(WORD *pwCrc) // calculate fingerprint of port2
static BOOL CrcPort2(WORD *pwCrc) // calculate fingerprint of port2
{
DWORD dwCount;
DWORD dwFileSize;
*pwCrc = 0;
// port2 CRC isn't available
if (pbyPort2 == NULL) return TRUE;
dwFileSize = GetFileSize(hPort2File, &dwCount); // get real filesize
_ASSERT(dwCount == 0); // isn't created by MapPort2()
for (dwCount = 0;dwCount < dwFileSize; ++dwCount)
if (pbyPort2 != NULL) // port2 CRC available
{
if ((pbyPort2[dwCount] & 0xF0) != 0) // data packed?
return FALSE;
LPBYTE pbyMem;
*pwCrc = (*pwCrc >> 4) ^ (((*pwCrc ^ ((WORD) pbyPort2[dwCount])) & 0xf) * 0x1081);
// get real filesize
DWORD dwFileSize = GetFileSize(hPort2File, NULL);
for (pbyMem = pbyPort2; dwFileSize > 0; --dwFileSize)
{
if ((*pbyMem & 0xF0) != 0) // data packed?
return FALSE;
*pwCrc = UpCRC(*pwCrc,*pbyMem++);
}
}
return TRUE;
}
@ -836,7 +843,7 @@ VOID ResetDocument(VOID)
hCurrentFile = NULL;
}
szCurrentKml[0] = 0;
szCurrentFilename[0]=0;
szCurrentFilename[0] = 0;
if (Port0) { free(Port0); Port0 = NULL; }
if (Port1) { free(Port1); Port1 = NULL; }
if (Port2) { free(Port2); Port2 = NULL; } else UnmapPort2();
@ -919,17 +926,17 @@ BOOL NewDocument(VOID)
if (Chipset.Port0Size)
{
Port0 = (LPBYTE) calloc(Chipset.Port0Size*2048,sizeof(*Port0));
_ASSERT(Port0 != NULL);
if (Port0 == NULL) goto restore;
}
if (Chipset.Port1Size)
{
Port1 = (LPBYTE) calloc(Chipset.Port1Size*2048,sizeof(*Port1));
_ASSERT(Port1 != NULL);
if (Port1 == NULL) goto restore;
}
if (Chipset.Port2Size)
{
Port2 = (LPBYTE) calloc(Chipset.Port2Size*2048,sizeof(*Port1));
_ASSERT(Port2 != NULL);
Port2 = (LPBYTE) calloc(Chipset.Port2Size*2048,sizeof(*Port2));
if (Port2 == NULL) goto restore;
}
LoadBreakpointList(NULL); // clear debugger breakpoint list
RomSwitch(0); // boot ROM view of HP49G and map memory
@ -958,10 +965,9 @@ BOOL OpenDocument(LPCTSTR szFilename)
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD lBytesRead,lSizeofChipset;
BYTE pbyFileSignature[16];
LPBYTE pbySig;
UINT ctBytesCompared;
UINT nLength;
BYTE byFileSignature[16];
BOOL bMatch;
UINT i,nLength;
// Open file
if (lstrcmpi(szCurrentFilename,szFilename) == 0)
@ -981,38 +987,19 @@ BOOL OpenDocument(LPCTSTR szFilename)
}
// Read and Compare signature
ReadFile(hFile, pbyFileSignature, 16, &lBytesRead, NULL);
switch (pbyFileSignature[0])
ReadFile(hFile, byFileSignature, sizeof(byFileSignature), &lBytesRead, NULL);
// go through all valid document signatures
for (bMatch = FALSE, i = 0; !bMatch && i < ARRAYSIZEOF(bySignature); ++i)
{
case 'E':
pbySig = (pbyFileSignature[3] == '3')
? ((pbyFileSignature[4] == '8') ? pbySignatureA : pbySignatureB)
: ((pbyFileSignature[4] == '8') ? pbySignatureE : pbySignatureV);
for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++)
{
if (pbyFileSignature[ctBytesCompared]!=pbySig[ctBytesCompared])
{
AbortMessage(_T("This file is not a valid Emu48 document."));
goto restore;
}
}
break;
case 'W':
for (ctBytesCompared=0; ctBytesCompared<14; ctBytesCompared++)
{
if (pbyFileSignature[ctBytesCompared]!=pbySignatureW[ctBytesCompared])
{
AbortMessage(_T("This file is not a valid Win48 document."));
goto restore;
}
}
break;
default:
AbortMessage(_T("This file is not a valid document."));
bMatch = (memcmp(byFileSignature, bySignature[i], sizeof(byFileSignature)) == 0);
}
if (!bMatch) // no valid document signature found
{
AbortMessage(_T("This file is not a valid Emu48 document."));
goto restore;
}
switch (pbyFileSignature[14])
switch (byFileSignature[14])
{
case 0xFE: // Win48 2.1 / Emu4x 0.99.x format
// read length of KML script name
@ -1051,8 +1038,7 @@ BOOL OpenDocument(LPCTSTR szFilename)
case 0xFF: // Win48 2.05 format
break;
default:
AbortMessage(_T("This file is for an unknown version of Emu48."));
goto restore;
_ASSERT(FALSE);
}
// read chipset size inside file
@ -1087,9 +1073,7 @@ BOOL OpenDocument(LPCTSTR szFilename)
{
if (szCurrentKml[0]) // KML file name
{
BOOL bOK;
bOK = InitKML(szCurrentKml,FALSE);
BOOL bOK = InitKML(szCurrentKml,FALSE);
bOK = bOK && (cCurrentRomType == Chipset.type);
if (bOK) break;
@ -1228,9 +1212,10 @@ BOOL SaveDocument(VOID)
SetFilePointer(hCurrentFile,0,NULL,FILE_BEGIN);
if (!WriteFile(hCurrentFile, pbySignatureE, sizeof(pbySignatureE), &lBytesWritten, NULL))
// write default "Emu48 Document\xFE" signature
if (!WriteFile(hCurrentFile, bySignature[0], 16, &lBytesWritten, NULL))
{
AbortMessage(_T("Could not write into file !"));
AbortMessage(_T("Could not write into document file!"));
return FALSE;
}
@ -1304,6 +1289,8 @@ BOOL SaveBackup(VOID)
{
WINDOWPLACEMENT wndpl;
BOOL bSucc = TRUE;
if (!bDocumentAvail) return FALSE;
_ASSERT(nState != SM_RUN); // emulation engine is running
@ -1324,27 +1311,41 @@ BOOL SaveBackup(VOID)
if (Port0 && Chipset.Port0Size)
{
BackupPort0 = (LPBYTE) malloc(Chipset.Port0Size*2048);
CopyMemory(BackupPort0,Port0,Chipset.Port0Size*2048);
if (BackupPort0)
{
CopyMemory(BackupPort0,Port0,Chipset.Port0Size*2048);
}
bSucc = bSucc && (BackupPort0 != NULL);
}
if (Port1 && Chipset.Port1Size)
{
BackupPort1 = (LPBYTE) malloc(Chipset.Port1Size*2048);
CopyMemory(BackupPort1,Port1,Chipset.Port1Size*2048);
if (BackupPort1)
{
CopyMemory(BackupPort1,Port1,Chipset.Port1Size*2048);
}
bSucc = bSucc && (BackupPort1 != NULL);
}
if (Port2 && Chipset.Port2Size) // internal port2
{
BackupPort2 = (LPBYTE) malloc(Chipset.Port2Size*2048);
CopyMemory(BackupPort2,Port2,Chipset.Port2Size*2048);
if (BackupPort2)
{
CopyMemory(BackupPort2,Port2,Chipset.Port2Size*2048);
}
bSucc = bSucc && (BackupPort2 != NULL);
}
CreateBackupBreakpointList();
bBackup = TRUE;
return TRUE;
bBackup = bSucc;
return bSucc;
}
BOOL RestoreBackup(VOID)
{
BOOL bDbgOpen;
BOOL bSucc = TRUE;
if (!bBackup) return FALSE;
bDbgOpen = (nDbgState != DBG_OFF); // debugger window open?
@ -1371,17 +1372,29 @@ BOOL RestoreBackup(VOID)
if (BackupPort0 && Chipset.Port0Size)
{
Port0 = (LPBYTE) malloc(Chipset.Port0Size*2048);
CopyMemory(Port0,BackupPort0,Chipset.Port0Size*2048);
if (Port0)
{
CopyMemory(Port0,BackupPort0,Chipset.Port0Size*2048);
}
bSucc = bSucc && (Port0 != NULL);
}
if (BackupPort1 && Chipset.Port1Size)
{
Port1 = (LPBYTE) malloc(Chipset.Port1Size*2048);
CopyMemory(Port1,BackupPort1,Chipset.Port1Size*2048);
if (Port1)
{
CopyMemory(Port1,BackupPort1,Chipset.Port1Size*2048);
}
bSucc = bSucc && (Port1 != NULL);
}
if (BackupPort2 && Chipset.Port2Size) // internal port2
{
Port2 = (LPBYTE) malloc(Chipset.Port2Size*2048);
CopyMemory(Port2,BackupPort2,Chipset.Port2Size*2048);
if (Port2)
{
CopyMemory(Port2,BackupPort2,Chipset.Port2Size*2048);
}
bSucc = bSucc && (Port2 != NULL);
}
// map port2
else
@ -1397,8 +1410,12 @@ BOOL RestoreBackup(VOID)
SetWindowLocation(hWnd,Chipset.nPosX,Chipset.nPosY);
RestoreBackupBreakpointList(); // restore the debugger breakpoint list
if (bDbgOpen) OnToolDebug(); // reopen the debugger
bDocumentAvail = TRUE; // document available
return TRUE;
if (!bSucc) // restore not successful (memory allocation errors)
{
ResetDocument(); // cleanup remainders
}
bDocumentAvail = bSucc; // document available
return bSucc;
}
BOOL ResetBackup(VOID)
@ -2610,7 +2627,6 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
BOOL (*fnColorCmp)(DWORD dwColor1,DWORD dwColor2,DWORD dwTol);
DWORD dwRed,dwGreen,dwBlue;
HRGN hRgn;
LPRGNDATA pRgnData;
LPBITMAPINFO bi;
LPBYTE pbyBits;
@ -2622,6 +2638,8 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
BOOL bFoundLeft;
BOOL bIsMask;
HRGN hRgn = NULL; // no region defined
if (dwTol >= 1000) // use CIE L*a*b compare
{
fnColorCmp = LabColorCmp;
@ -2633,7 +2651,10 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
}
// allocate memory for extended image information incl. RGBQUAD color table
bi = (LPBITMAPINFO) calloc(1,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
if ((bi = (LPBITMAPINFO) calloc(1,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD))) == NULL)
{
return hRgn; // no region
}
bi->bmiHeader.biSize = sizeof(bi->bmiHeader);
_ASSERT(bi->bmiHeader.biBitCount == 0); // for query without color table
@ -2652,7 +2673,11 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
}
// allocate memory for image data (colors)
pbyBits = (LPBYTE) malloc(bi->bmiHeader.biSizeImage);
if ((pbyBits = (LPBYTE) malloc(bi->bmiHeader.biSizeImage)) == NULL)
{
free(bi); // free bitmap info
return hRgn; // no region
}
// fill bits buffer
GetDIBits(hWindowDC,hBmp,0,bi->bmiHeader.biHeight,pbyBits,bi,DIB_RGB_COLORS);
@ -2697,18 +2722,20 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
// allocate memory for region data
pRgnData = (PRGNDATA) malloc(sizeof(RGNDATAHEADER) + dwRectsCount * sizeof(RECT));
if (pRgnData)
{
// fill it by default
ZeroMemory(&pRgnData->rdh,sizeof(pRgnData->rdh));
pRgnData->rdh.dwSize = sizeof(pRgnData->rdh);
pRgnData->rdh.iType = RDH_RECTANGLES;
SetRect(&pRgnData->rdh.rcBound,MAXLONG,MAXLONG,0,0);
}
// fill it by default
ZeroMemory(&pRgnData->rdh,sizeof(pRgnData->rdh));
pRgnData->rdh.dwSize = sizeof(pRgnData->rdh);
pRgnData->rdh.iType = RDH_RECTANGLES;
SetRect(&pRgnData->rdh.rcBound,MAXLONG,MAXLONG,0,0);
for (y = 0; y < bi->bmiHeader.biHeight; ++y)
for (y = 0; pRgnData && y < bi->bmiHeader.biHeight; ++y)
{
LPBYTE pbyLineStart = pbyColor;
for (x = 0; x < bi->bmiHeader.biWidth; ++x)
for (x = 0; pRgnData && x < bi->bmiHeader.biWidth; ++x)
{
// get color
switch (bi->bmiHeader.biBitCount)
@ -2765,9 +2792,19 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
// if buffer full reallocate it with more room
if (pRgnData->rdh.nCount >= dwRectsCount)
{
dwRectsCount += ADD_RECTS_COUNT;
LPRGNDATA pNewRgnData;
pRgnData = (LPRGNDATA) realloc(pRgnData,sizeof(RGNDATAHEADER) + dwRectsCount * sizeof(RECT));
dwRectsCount += ADD_RECTS_COUNT;
pNewRgnData = (LPRGNDATA) realloc(pRgnData,sizeof(RGNDATAHEADER) + dwRectsCount * sizeof(RECT));
if (pNewRgnData)
{
pRgnData = pNewRgnData;
}
else
{
free(pRgnData);
pRgnData = NULL;
}
}
bFoundLeft = FALSE;
@ -2782,10 +2819,11 @@ HRGN CreateRgnFromBitmap(HBITMAP hBmp,COLORREF color,DWORD dwTol)
free(pbyBits);
free(bi);
// create region
hRgn = ExtCreateRegion(NULL,sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT),pRgnData);
free(pRgnData);
if (pRgnData) // has region data, create region
{
hRgn = ExtCreateRegion(NULL,sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT),pRgnData);
free(pRgnData);
}
return hRgn;
#undef ADD_RECTS_COUNT
}

View file

@ -165,30 +165,23 @@ static VOID ClearLog()
static VOID AddToLog(LPCTSTR szString)
{
LPTSTR szLogTmp;
UINT nLength = lstrlen(szString) + 2; // CR+LF
if (szLog == NULL)
if (szLog == NULL) // no log
{
nLogLength = nLength + 1; // \0
szLog = (LPTSTR) malloc(nLogLength*sizeof(szLog[0]));
if (szLog==NULL)
{
nLogLength = 0;
return;
}
lstrcpy(szLog,szString);
nLogLength = 1; // room for \0
}
else
szLogTmp = (LPTSTR) realloc(szLog,(nLogLength+nLength)*sizeof(szLog[0]));
if (szLogTmp == NULL)
{
LPTSTR szLogTmp = (LPTSTR) realloc(szLog,(nLogLength+nLength)*sizeof(szLog[0]));
if (szLogTmp == NULL)
{
ClearLog();
return;
}
szLog = szLogTmp;
lstrcpy(&szLog[nLogLength-1],szString);
nLogLength += nLength;
ClearLog();
return;
}
szLog = szLogTmp;
lstrcpy(&szLog[nLogLength-1],szString);
nLogLength += nLength;
szLog[nLogLength-3] = _T('\r');
szLog[nLogLength-2] = _T('\n');
szLog[nLogLength-1] = 0;
@ -274,11 +267,9 @@ static CHAR cKmlType;
static VOID DestroyKmlList(VOID)
{
KmlScript* pList;
while (pKmlList)
{
pList = pKmlList->pNext;
KmlScript* pList = pKmlList->pNext;
free(pKmlList->szFilename);
free(pKmlList->szTitle);
free(pKmlList);
@ -304,36 +295,45 @@ static VOID CreateKmlList(VOID)
KmlScript* pScript;
KmlBlock* pBlock;
LPCTSTR szTitle;
BOOL bInvalidPlatform;
pBlock = LoadKMLGlobal(pFindFileData.cFileName);
if (pBlock == NULL) continue;
// check for correct KML script platform
szTitle = GetStringParam(pBlock,TOK_GLOBAL,TOK_HARDWARE,0);
if (szTitle && lstrcmpi(_T(HARDWARE),szTitle) != 0)
{
FreeBlocks(pBlock);
continue;
}
bInvalidPlatform = (szTitle && lstrcmpi(_T(HARDWARE),szTitle) != 0);
// check for supported Model
szTitle = GetStringParam(pBlock,TOK_GLOBAL,TOK_MODEL,0);
// skip all scripts with invalid or different Model statement
if ( (szTitle == NULL)
// skip all scripts with invalid platform and invalid or different Model statement
if ( bInvalidPlatform
|| (szTitle == NULL)
|| (cKmlType && szTitle[0] != cKmlType)
|| !isModelValid(szTitle[0]))
{
FreeBlocks(pBlock);
continue;
}
VERIFY(pScript = (KmlScript*) malloc(sizeof(KmlScript)));
pScript->szFilename = DuplicateString(pFindFileData.cFileName);
szTitle = GetStringParam(pBlock,TOK_GLOBAL,TOK_TITLE,0);
if (szTitle == NULL) szTitle = pScript->szFilename;
pScript->szTitle = DuplicateString(szTitle);
pScript = (KmlScript*) malloc(sizeof(KmlScript));
if (pScript) // script node allocated
{
pScript->szFilename = DuplicateString(pFindFileData.cFileName);
szTitle = GetStringParam(pBlock,TOK_GLOBAL,TOK_TITLE,0);
if (szTitle == NULL) szTitle = pScript->szFilename;
pScript->szTitle = DuplicateString(szTitle);
if (pScript->szFilename == NULL || pScript->szTitle == NULL)
{
free(pScript->szFilename);
free(pScript->szTitle);
free(pScript);
FreeBlocks(pBlock);
continue;
}
pScript->nId = nKmlFiles;
pScript->pNext = pKmlList;
pKmlList = pScript;
nKmlFiles++;
}
FreeBlocks(pBlock);
pScript->nId = nKmlFiles;
pScript->pNext = pKmlList;
pKmlList = pScript;
nKmlFiles++;
} while (FindNextFile(hFindFile,&pFindFileData));
FindClose(hFindFile);
return;
@ -677,20 +677,29 @@ static DWORD ParseInteger(VOID)
static LPTSTR ParseString(VOID)
{
LPTSTR lpszString;
UINT nLength;
UINT nBlock;
LPTSTR lpszString = NULL; // no mem allocated
UINT nBlock = 0;
UINT nLength = 0;
LPTSTR lpszAllocString;
szText++; // skip leading '"'
nLength = 0;
nBlock = 256;
lpszString = (LPTSTR) malloc(nBlock * sizeof(lpszString[0]));
while (*szText != _T('"'))
{
if (nLength == nBlock - 1) // ran out of buffer space
if (nLength >= nBlock) // ran out of buffer space
{
nBlock += 256;
lpszString = (LPTSTR) realloc(lpszString,nBlock * sizeof(lpszString[0]));
lpszAllocString = (LPTSTR) realloc(lpszString,nBlock * sizeof(lpszString[0]));
if (lpszAllocString)
{
lpszString = lpszAllocString;
}
else
{
free(lpszString); // cleanup allocation failture
return NULL;
}
}
if (*szText == _T('\\')) // escape char
@ -716,10 +725,17 @@ static LPTSTR ParseString(VOID)
lpszString[nLength++] = *szText++; // save char
}
szText++; // skip ending '"'
lpszString[nLength] = 0; // set EOS
// release unnecessary allocated bytes
return (LPTSTR) realloc(lpszString,(nLength+1) * sizeof(lpszString[0]));
// release unnecessary allocated bytes or allocate byte for EOS
if ((lpszAllocString = (LPTSTR) realloc(lpszString,(nLength+1) * sizeof(lpszString[0]))))
{
lpszAllocString[nLength] = 0; // set EOS
}
else
{
free(lpszString); // cleanup allocation failture
}
return lpszAllocString;
}
static TokenId Lex(UINT nMode)
@ -767,7 +783,9 @@ static KmlLine* ParseLine(TokenId eCommand)
}
if (pLexToken[i].nLen == 0) return NULL;
pLine = (KmlLine*) calloc(1,sizeof(KmlLine));
if ((pLine = (KmlLine*) calloc(1,sizeof(KmlLine))) == NULL)
return NULL;
pLine->eCommand = eCommand;
for (j = 0, nParams = pLexToken[i].nParams; TRUE; nParams >>= 3)
@ -946,7 +964,10 @@ static KmlLine* ParseLines(BOOL bInclude)
if (pFirst == NULL) // regular exit with empty block
{
// create an empty line
pLine = pFirst = (KmlLine*) calloc(1,sizeof(KmlLine));
if ((pFirst = (KmlLine*) calloc(1,sizeof(KmlLine))) == NULL)
goto abort;
pLine = pFirst;
pLine->eCommand = TOK_NONE;
}
if (pLine) pLine->pNext = NULL;
@ -985,7 +1006,9 @@ static KmlBlock* ParseBlock(BOOL bInclude, TokenId eType)
nLinesIncludeLevel = 0;
VERIFY(pBlock = (KmlBlock *) calloc(1,sizeof(KmlBlock)));
if ((pBlock = (KmlBlock *) calloc(1,sizeof(KmlBlock))) == NULL)
return NULL;
pBlock->eType = eType;
for (i = 0; pLexToken[i].nLen; ++i) // search for token
@ -1829,7 +1852,7 @@ static VOID AdjustPixel(LPBYTE pbyPixel, BYTE byOffset)
{
INT i = 3; // BGR colors
while (--i >= 0)
while (--i >= 0)
{
WORD wColor = (WORD) *pbyPixel + byOffset;
// jumpless saturation to 0xFF
@ -2618,6 +2641,11 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
AddToLog(_T("This KML Script doesn't specify the ROM to use, or the ROM could not be loaded."));
goto quit;
}
if (bRomCrcCorrection) // ROM CRC correction enabled
{
AddToLog(_T("Rebuild the ROM CRC."));
RebuildRomCrc(); // rebuild the ROM CRC's
}
if (hMainDC == NULL)
{
AddToLog(_T("This KML Script doesn't specify the background bitmap, or bitmap could not be loaded."));

View file

@ -1,7 +1,7 @@
/*
LodePNG version 20220717
LodePNG version 20230410
Copyright (c) 2005-2022 Lode Vandevenne
Copyright (c) 2005-2023 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -44,7 +44,7 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */
const char* LODEPNG_VERSION_STRING = "20220717";
const char* LODEPNG_VERSION_STRING = "20230410";
/*
This source file is divided into the following large parts. The code sections
@ -140,7 +140,6 @@ static size_t lodepng_strlen(const char* a) {
#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b))
#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
#define LODEPNG_ABS(x) ((x) < 0 ? -(x) : (x))
#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)
/* Safely check if adding two integers will overflow (no undefined
@ -2374,54 +2373,328 @@ const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0,
#ifdef LODEPNG_COMPILE_CRC
/* CRC polynomial: 0xedb88320 */
static unsigned lodepng_crc32_table[256] = {
0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u,
498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u,
325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u,
997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u,
651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u,
671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u,
1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u,
2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u,
1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u,
1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u,
1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u,
3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u,
3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u,
4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u,
4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u,
3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u,
3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u,
2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u,
2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u,
2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u,
2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u,
3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
static const unsigned lodepng_crc32_table0[256] = {
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u,
0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,
0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u,
0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u,
0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u,
0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu,
0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du,
0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u,
0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u,
0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu,
0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u,
0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu,
0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u,
0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u,
0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu,
0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u,
0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du,
0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u,
0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du
};
/*Return the CRC of the bytes buf[0..len-1].*/
static const unsigned lodepng_crc32_table1[256] = {
0x00000000u, 0x191b3141u, 0x32366282u, 0x2b2d53c3u, 0x646cc504u, 0x7d77f445u, 0x565aa786u, 0x4f4196c7u,
0xc8d98a08u, 0xd1c2bb49u, 0xfaefe88au, 0xe3f4d9cbu, 0xacb54f0cu, 0xb5ae7e4du, 0x9e832d8eu, 0x87981ccfu,
0x4ac21251u, 0x53d92310u, 0x78f470d3u, 0x61ef4192u, 0x2eaed755u, 0x37b5e614u, 0x1c98b5d7u, 0x05838496u,
0x821b9859u, 0x9b00a918u, 0xb02dfadbu, 0xa936cb9au, 0xe6775d5du, 0xff6c6c1cu, 0xd4413fdfu, 0xcd5a0e9eu,
0x958424a2u, 0x8c9f15e3u, 0xa7b24620u, 0xbea97761u, 0xf1e8e1a6u, 0xe8f3d0e7u, 0xc3de8324u, 0xdac5b265u,
0x5d5daeaau, 0x44469febu, 0x6f6bcc28u, 0x7670fd69u, 0x39316baeu, 0x202a5aefu, 0x0b07092cu, 0x121c386du,
0xdf4636f3u, 0xc65d07b2u, 0xed705471u, 0xf46b6530u, 0xbb2af3f7u, 0xa231c2b6u, 0x891c9175u, 0x9007a034u,
0x179fbcfbu, 0x0e848dbau, 0x25a9de79u, 0x3cb2ef38u, 0x73f379ffu, 0x6ae848beu, 0x41c51b7du, 0x58de2a3cu,
0xf0794f05u, 0xe9627e44u, 0xc24f2d87u, 0xdb541cc6u, 0x94158a01u, 0x8d0ebb40u, 0xa623e883u, 0xbf38d9c2u,
0x38a0c50du, 0x21bbf44cu, 0x0a96a78fu, 0x138d96ceu, 0x5ccc0009u, 0x45d73148u, 0x6efa628bu, 0x77e153cau,
0xbabb5d54u, 0xa3a06c15u, 0x888d3fd6u, 0x91960e97u, 0xded79850u, 0xc7cca911u, 0xece1fad2u, 0xf5facb93u,
0x7262d75cu, 0x6b79e61du, 0x4054b5deu, 0x594f849fu, 0x160e1258u, 0x0f152319u, 0x243870dau, 0x3d23419bu,
0x65fd6ba7u, 0x7ce65ae6u, 0x57cb0925u, 0x4ed03864u, 0x0191aea3u, 0x188a9fe2u, 0x33a7cc21u, 0x2abcfd60u,
0xad24e1afu, 0xb43fd0eeu, 0x9f12832du, 0x8609b26cu, 0xc94824abu, 0xd05315eau, 0xfb7e4629u, 0xe2657768u,
0x2f3f79f6u, 0x362448b7u, 0x1d091b74u, 0x04122a35u, 0x4b53bcf2u, 0x52488db3u, 0x7965de70u, 0x607eef31u,
0xe7e6f3feu, 0xfefdc2bfu, 0xd5d0917cu, 0xcccba03du, 0x838a36fau, 0x9a9107bbu, 0xb1bc5478u, 0xa8a76539u,
0x3b83984bu, 0x2298a90au, 0x09b5fac9u, 0x10aecb88u, 0x5fef5d4fu, 0x46f46c0eu, 0x6dd93fcdu, 0x74c20e8cu,
0xf35a1243u, 0xea412302u, 0xc16c70c1u, 0xd8774180u, 0x9736d747u, 0x8e2de606u, 0xa500b5c5u, 0xbc1b8484u,
0x71418a1au, 0x685abb5bu, 0x4377e898u, 0x5a6cd9d9u, 0x152d4f1eu, 0x0c367e5fu, 0x271b2d9cu, 0x3e001cddu,
0xb9980012u, 0xa0833153u, 0x8bae6290u, 0x92b553d1u, 0xddf4c516u, 0xc4eff457u, 0xefc2a794u, 0xf6d996d5u,
0xae07bce9u, 0xb71c8da8u, 0x9c31de6bu, 0x852aef2au, 0xca6b79edu, 0xd37048acu, 0xf85d1b6fu, 0xe1462a2eu,
0x66de36e1u, 0x7fc507a0u, 0x54e85463u, 0x4df36522u, 0x02b2f3e5u, 0x1ba9c2a4u, 0x30849167u, 0x299fa026u,
0xe4c5aeb8u, 0xfdde9ff9u, 0xd6f3cc3au, 0xcfe8fd7bu, 0x80a96bbcu, 0x99b25afdu, 0xb29f093eu, 0xab84387fu,
0x2c1c24b0u, 0x350715f1u, 0x1e2a4632u, 0x07317773u, 0x4870e1b4u, 0x516bd0f5u, 0x7a468336u, 0x635db277u,
0xcbfad74eu, 0xd2e1e60fu, 0xf9ccb5ccu, 0xe0d7848du, 0xaf96124au, 0xb68d230bu, 0x9da070c8u, 0x84bb4189u,
0x03235d46u, 0x1a386c07u, 0x31153fc4u, 0x280e0e85u, 0x674f9842u, 0x7e54a903u, 0x5579fac0u, 0x4c62cb81u,
0x8138c51fu, 0x9823f45eu, 0xb30ea79du, 0xaa1596dcu, 0xe554001bu, 0xfc4f315au, 0xd7626299u, 0xce7953d8u,
0x49e14f17u, 0x50fa7e56u, 0x7bd72d95u, 0x62cc1cd4u, 0x2d8d8a13u, 0x3496bb52u, 0x1fbbe891u, 0x06a0d9d0u,
0x5e7ef3ecu, 0x4765c2adu, 0x6c48916eu, 0x7553a02fu, 0x3a1236e8u, 0x230907a9u, 0x0824546au, 0x113f652bu,
0x96a779e4u, 0x8fbc48a5u, 0xa4911b66u, 0xbd8a2a27u, 0xf2cbbce0u, 0xebd08da1u, 0xc0fdde62u, 0xd9e6ef23u,
0x14bce1bdu, 0x0da7d0fcu, 0x268a833fu, 0x3f91b27eu, 0x70d024b9u, 0x69cb15f8u, 0x42e6463bu, 0x5bfd777au,
0xdc656bb5u, 0xc57e5af4u, 0xee530937u, 0xf7483876u, 0xb809aeb1u, 0xa1129ff0u, 0x8a3fcc33u, 0x9324fd72u
};
static const unsigned lodepng_crc32_table2[256] = {
0x00000000u, 0x01c26a37u, 0x0384d46eu, 0x0246be59u, 0x0709a8dcu, 0x06cbc2ebu, 0x048d7cb2u, 0x054f1685u,
0x0e1351b8u, 0x0fd13b8fu, 0x0d9785d6u, 0x0c55efe1u, 0x091af964u, 0x08d89353u, 0x0a9e2d0au, 0x0b5c473du,
0x1c26a370u, 0x1de4c947u, 0x1fa2771eu, 0x1e601d29u, 0x1b2f0bacu, 0x1aed619bu, 0x18abdfc2u, 0x1969b5f5u,
0x1235f2c8u, 0x13f798ffu, 0x11b126a6u, 0x10734c91u, 0x153c5a14u, 0x14fe3023u, 0x16b88e7au, 0x177ae44du,
0x384d46e0u, 0x398f2cd7u, 0x3bc9928eu, 0x3a0bf8b9u, 0x3f44ee3cu, 0x3e86840bu, 0x3cc03a52u, 0x3d025065u,
0x365e1758u, 0x379c7d6fu, 0x35dac336u, 0x3418a901u, 0x3157bf84u, 0x3095d5b3u, 0x32d36beau, 0x331101ddu,
0x246be590u, 0x25a98fa7u, 0x27ef31feu, 0x262d5bc9u, 0x23624d4cu, 0x22a0277bu, 0x20e69922u, 0x2124f315u,
0x2a78b428u, 0x2bbade1fu, 0x29fc6046u, 0x283e0a71u, 0x2d711cf4u, 0x2cb376c3u, 0x2ef5c89au, 0x2f37a2adu,
0x709a8dc0u, 0x7158e7f7u, 0x731e59aeu, 0x72dc3399u, 0x7793251cu, 0x76514f2bu, 0x7417f172u, 0x75d59b45u,
0x7e89dc78u, 0x7f4bb64fu, 0x7d0d0816u, 0x7ccf6221u, 0x798074a4u, 0x78421e93u, 0x7a04a0cau, 0x7bc6cafdu,
0x6cbc2eb0u, 0x6d7e4487u, 0x6f38fadeu, 0x6efa90e9u, 0x6bb5866cu, 0x6a77ec5bu, 0x68315202u, 0x69f33835u,
0x62af7f08u, 0x636d153fu, 0x612bab66u, 0x60e9c151u, 0x65a6d7d4u, 0x6464bde3u, 0x662203bau, 0x67e0698du,
0x48d7cb20u, 0x4915a117u, 0x4b531f4eu, 0x4a917579u, 0x4fde63fcu, 0x4e1c09cbu, 0x4c5ab792u, 0x4d98dda5u,
0x46c49a98u, 0x4706f0afu, 0x45404ef6u, 0x448224c1u, 0x41cd3244u, 0x400f5873u, 0x4249e62au, 0x438b8c1du,
0x54f16850u, 0x55330267u, 0x5775bc3eu, 0x56b7d609u, 0x53f8c08cu, 0x523aaabbu, 0x507c14e2u, 0x51be7ed5u,
0x5ae239e8u, 0x5b2053dfu, 0x5966ed86u, 0x58a487b1u, 0x5deb9134u, 0x5c29fb03u, 0x5e6f455au, 0x5fad2f6du,
0xe1351b80u, 0xe0f771b7u, 0xe2b1cfeeu, 0xe373a5d9u, 0xe63cb35cu, 0xe7fed96bu, 0xe5b86732u, 0xe47a0d05u,
0xef264a38u, 0xeee4200fu, 0xeca29e56u, 0xed60f461u, 0xe82fe2e4u, 0xe9ed88d3u, 0xebab368au, 0xea695cbdu,
0xfd13b8f0u, 0xfcd1d2c7u, 0xfe976c9eu, 0xff5506a9u, 0xfa1a102cu, 0xfbd87a1bu, 0xf99ec442u, 0xf85cae75u,
0xf300e948u, 0xf2c2837fu, 0xf0843d26u, 0xf1465711u, 0xf4094194u, 0xf5cb2ba3u, 0xf78d95fau, 0xf64fffcdu,
0xd9785d60u, 0xd8ba3757u, 0xdafc890eu, 0xdb3ee339u, 0xde71f5bcu, 0xdfb39f8bu, 0xddf521d2u, 0xdc374be5u,
0xd76b0cd8u, 0xd6a966efu, 0xd4efd8b6u, 0xd52db281u, 0xd062a404u, 0xd1a0ce33u, 0xd3e6706au, 0xd2241a5du,
0xc55efe10u, 0xc49c9427u, 0xc6da2a7eu, 0xc7184049u, 0xc25756ccu, 0xc3953cfbu, 0xc1d382a2u, 0xc011e895u,
0xcb4dafa8u, 0xca8fc59fu, 0xc8c97bc6u, 0xc90b11f1u, 0xcc440774u, 0xcd866d43u, 0xcfc0d31au, 0xce02b92du,
0x91af9640u, 0x906dfc77u, 0x922b422eu, 0x93e92819u, 0x96a63e9cu, 0x976454abu, 0x9522eaf2u, 0x94e080c5u,
0x9fbcc7f8u, 0x9e7eadcfu, 0x9c381396u, 0x9dfa79a1u, 0x98b56f24u, 0x99770513u, 0x9b31bb4au, 0x9af3d17du,
0x8d893530u, 0x8c4b5f07u, 0x8e0de15eu, 0x8fcf8b69u, 0x8a809decu, 0x8b42f7dbu, 0x89044982u, 0x88c623b5u,
0x839a6488u, 0x82580ebfu, 0x801eb0e6u, 0x81dcdad1u, 0x8493cc54u, 0x8551a663u, 0x8717183au, 0x86d5720du,
0xa9e2d0a0u, 0xa820ba97u, 0xaa6604ceu, 0xaba46ef9u, 0xaeeb787cu, 0xaf29124bu, 0xad6fac12u, 0xacadc625u,
0xa7f18118u, 0xa633eb2fu, 0xa4755576u, 0xa5b73f41u, 0xa0f829c4u, 0xa13a43f3u, 0xa37cfdaau, 0xa2be979du,
0xb5c473d0u, 0xb40619e7u, 0xb640a7beu, 0xb782cd89u, 0xb2cddb0cu, 0xb30fb13bu, 0xb1490f62u, 0xb08b6555u,
0xbbd72268u, 0xba15485fu, 0xb853f606u, 0xb9919c31u, 0xbcde8ab4u, 0xbd1ce083u, 0xbf5a5edau, 0xbe9834edu
};
static const unsigned lodepng_crc32_table3[256] = {
0x00000000u, 0xb8bc6765u, 0xaa09c88bu, 0x12b5afeeu, 0x8f629757u, 0x37def032u, 0x256b5fdcu, 0x9dd738b9u,
0xc5b428efu, 0x7d084f8au, 0x6fbde064u, 0xd7018701u, 0x4ad6bfb8u, 0xf26ad8ddu, 0xe0df7733u, 0x58631056u,
0x5019579fu, 0xe8a530fau, 0xfa109f14u, 0x42acf871u, 0xdf7bc0c8u, 0x67c7a7adu, 0x75720843u, 0xcdce6f26u,
0x95ad7f70u, 0x2d111815u, 0x3fa4b7fbu, 0x8718d09eu, 0x1acfe827u, 0xa2738f42u, 0xb0c620acu, 0x087a47c9u,
0xa032af3eu, 0x188ec85bu, 0x0a3b67b5u, 0xb28700d0u, 0x2f503869u, 0x97ec5f0cu, 0x8559f0e2u, 0x3de59787u,
0x658687d1u, 0xdd3ae0b4u, 0xcf8f4f5au, 0x7733283fu, 0xeae41086u, 0x525877e3u, 0x40edd80du, 0xf851bf68u,
0xf02bf8a1u, 0x48979fc4u, 0x5a22302au, 0xe29e574fu, 0x7f496ff6u, 0xc7f50893u, 0xd540a77du, 0x6dfcc018u,
0x359fd04eu, 0x8d23b72bu, 0x9f9618c5u, 0x272a7fa0u, 0xbafd4719u, 0x0241207cu, 0x10f48f92u, 0xa848e8f7u,
0x9b14583du, 0x23a83f58u, 0x311d90b6u, 0x89a1f7d3u, 0x1476cf6au, 0xaccaa80fu, 0xbe7f07e1u, 0x06c36084u,
0x5ea070d2u, 0xe61c17b7u, 0xf4a9b859u, 0x4c15df3cu, 0xd1c2e785u, 0x697e80e0u, 0x7bcb2f0eu, 0xc377486bu,
0xcb0d0fa2u, 0x73b168c7u, 0x6104c729u, 0xd9b8a04cu, 0x446f98f5u, 0xfcd3ff90u, 0xee66507eu, 0x56da371bu,
0x0eb9274du, 0xb6054028u, 0xa4b0efc6u, 0x1c0c88a3u, 0x81dbb01au, 0x3967d77fu, 0x2bd27891u, 0x936e1ff4u,
0x3b26f703u, 0x839a9066u, 0x912f3f88u, 0x299358edu, 0xb4446054u, 0x0cf80731u, 0x1e4da8dfu, 0xa6f1cfbau,
0xfe92dfecu, 0x462eb889u, 0x549b1767u, 0xec277002u, 0x71f048bbu, 0xc94c2fdeu, 0xdbf98030u, 0x6345e755u,
0x6b3fa09cu, 0xd383c7f9u, 0xc1366817u, 0x798a0f72u, 0xe45d37cbu, 0x5ce150aeu, 0x4e54ff40u, 0xf6e89825u,
0xae8b8873u, 0x1637ef16u, 0x048240f8u, 0xbc3e279du, 0x21e91f24u, 0x99557841u, 0x8be0d7afu, 0x335cb0cau,
0xed59b63bu, 0x55e5d15eu, 0x47507eb0u, 0xffec19d5u, 0x623b216cu, 0xda874609u, 0xc832e9e7u, 0x708e8e82u,
0x28ed9ed4u, 0x9051f9b1u, 0x82e4565fu, 0x3a58313au, 0xa78f0983u, 0x1f336ee6u, 0x0d86c108u, 0xb53aa66du,
0xbd40e1a4u, 0x05fc86c1u, 0x1749292fu, 0xaff54e4au, 0x322276f3u, 0x8a9e1196u, 0x982bbe78u, 0x2097d91du,
0x78f4c94bu, 0xc048ae2eu, 0xd2fd01c0u, 0x6a4166a5u, 0xf7965e1cu, 0x4f2a3979u, 0x5d9f9697u, 0xe523f1f2u,
0x4d6b1905u, 0xf5d77e60u, 0xe762d18eu, 0x5fdeb6ebu, 0xc2098e52u, 0x7ab5e937u, 0x680046d9u, 0xd0bc21bcu,
0x88df31eau, 0x3063568fu, 0x22d6f961u, 0x9a6a9e04u, 0x07bda6bdu, 0xbf01c1d8u, 0xadb46e36u, 0x15080953u,
0x1d724e9au, 0xa5ce29ffu, 0xb77b8611u, 0x0fc7e174u, 0x9210d9cdu, 0x2aacbea8u, 0x38191146u, 0x80a57623u,
0xd8c66675u, 0x607a0110u, 0x72cfaefeu, 0xca73c99bu, 0x57a4f122u, 0xef189647u, 0xfdad39a9u, 0x45115eccu,
0x764dee06u, 0xcef18963u, 0xdc44268du, 0x64f841e8u, 0xf92f7951u, 0x41931e34u, 0x5326b1dau, 0xeb9ad6bfu,
0xb3f9c6e9u, 0x0b45a18cu, 0x19f00e62u, 0xa14c6907u, 0x3c9b51beu, 0x842736dbu, 0x96929935u, 0x2e2efe50u,
0x2654b999u, 0x9ee8defcu, 0x8c5d7112u, 0x34e11677u, 0xa9362eceu, 0x118a49abu, 0x033fe645u, 0xbb838120u,
0xe3e09176u, 0x5b5cf613u, 0x49e959fdu, 0xf1553e98u, 0x6c820621u, 0xd43e6144u, 0xc68bceaau, 0x7e37a9cfu,
0xd67f4138u, 0x6ec3265du, 0x7c7689b3u, 0xc4caeed6u, 0x591dd66fu, 0xe1a1b10au, 0xf3141ee4u, 0x4ba87981u,
0x13cb69d7u, 0xab770eb2u, 0xb9c2a15cu, 0x017ec639u, 0x9ca9fe80u, 0x241599e5u, 0x36a0360bu, 0x8e1c516eu,
0x866616a7u, 0x3eda71c2u, 0x2c6fde2cu, 0x94d3b949u, 0x090481f0u, 0xb1b8e695u, 0xa30d497bu, 0x1bb12e1eu,
0x43d23e48u, 0xfb6e592du, 0xe9dbf6c3u, 0x516791a6u, 0xccb0a91fu, 0x740cce7au, 0x66b96194u, 0xde0506f1u
};
static const unsigned lodepng_crc32_table4[256] = {
0x00000000u, 0x3d6029b0u, 0x7ac05360u, 0x47a07ad0u, 0xf580a6c0u, 0xc8e08f70u, 0x8f40f5a0u, 0xb220dc10u,
0x30704bc1u, 0x0d106271u, 0x4ab018a1u, 0x77d03111u, 0xc5f0ed01u, 0xf890c4b1u, 0xbf30be61u, 0x825097d1u,
0x60e09782u, 0x5d80be32u, 0x1a20c4e2u, 0x2740ed52u, 0x95603142u, 0xa80018f2u, 0xefa06222u, 0xd2c04b92u,
0x5090dc43u, 0x6df0f5f3u, 0x2a508f23u, 0x1730a693u, 0xa5107a83u, 0x98705333u, 0xdfd029e3u, 0xe2b00053u,
0xc1c12f04u, 0xfca106b4u, 0xbb017c64u, 0x866155d4u, 0x344189c4u, 0x0921a074u, 0x4e81daa4u, 0x73e1f314u,
0xf1b164c5u, 0xccd14d75u, 0x8b7137a5u, 0xb6111e15u, 0x0431c205u, 0x3951ebb5u, 0x7ef19165u, 0x4391b8d5u,
0xa121b886u, 0x9c419136u, 0xdbe1ebe6u, 0xe681c256u, 0x54a11e46u, 0x69c137f6u, 0x2e614d26u, 0x13016496u,
0x9151f347u, 0xac31daf7u, 0xeb91a027u, 0xd6f18997u, 0x64d15587u, 0x59b17c37u, 0x1e1106e7u, 0x23712f57u,
0x58f35849u, 0x659371f9u, 0x22330b29u, 0x1f532299u, 0xad73fe89u, 0x9013d739u, 0xd7b3ade9u, 0xead38459u,
0x68831388u, 0x55e33a38u, 0x124340e8u, 0x2f236958u, 0x9d03b548u, 0xa0639cf8u, 0xe7c3e628u, 0xdaa3cf98u,
0x3813cfcbu, 0x0573e67bu, 0x42d39cabu, 0x7fb3b51bu, 0xcd93690bu, 0xf0f340bbu, 0xb7533a6bu, 0x8a3313dbu,
0x0863840au, 0x3503adbau, 0x72a3d76au, 0x4fc3fedau, 0xfde322cau, 0xc0830b7au, 0x872371aau, 0xba43581au,
0x9932774du, 0xa4525efdu, 0xe3f2242du, 0xde920d9du, 0x6cb2d18du, 0x51d2f83du, 0x167282edu, 0x2b12ab5du,
0xa9423c8cu, 0x9422153cu, 0xd3826fecu, 0xeee2465cu, 0x5cc29a4cu, 0x61a2b3fcu, 0x2602c92cu, 0x1b62e09cu,
0xf9d2e0cfu, 0xc4b2c97fu, 0x8312b3afu, 0xbe729a1fu, 0x0c52460fu, 0x31326fbfu, 0x7692156fu, 0x4bf23cdfu,
0xc9a2ab0eu, 0xf4c282beu, 0xb362f86eu, 0x8e02d1deu, 0x3c220dceu, 0x0142247eu, 0x46e25eaeu, 0x7b82771eu,
0xb1e6b092u, 0x8c869922u, 0xcb26e3f2u, 0xf646ca42u, 0x44661652u, 0x79063fe2u, 0x3ea64532u, 0x03c66c82u,
0x8196fb53u, 0xbcf6d2e3u, 0xfb56a833u, 0xc6368183u, 0x74165d93u, 0x49767423u, 0x0ed60ef3u, 0x33b62743u,
0xd1062710u, 0xec660ea0u, 0xabc67470u, 0x96a65dc0u, 0x248681d0u, 0x19e6a860u, 0x5e46d2b0u, 0x6326fb00u,
0xe1766cd1u, 0xdc164561u, 0x9bb63fb1u, 0xa6d61601u, 0x14f6ca11u, 0x2996e3a1u, 0x6e369971u, 0x5356b0c1u,
0x70279f96u, 0x4d47b626u, 0x0ae7ccf6u, 0x3787e546u, 0x85a73956u, 0xb8c710e6u, 0xff676a36u, 0xc2074386u,
0x4057d457u, 0x7d37fde7u, 0x3a978737u, 0x07f7ae87u, 0xb5d77297u, 0x88b75b27u, 0xcf1721f7u, 0xf2770847u,
0x10c70814u, 0x2da721a4u, 0x6a075b74u, 0x576772c4u, 0xe547aed4u, 0xd8278764u, 0x9f87fdb4u, 0xa2e7d404u,
0x20b743d5u, 0x1dd76a65u, 0x5a7710b5u, 0x67173905u, 0xd537e515u, 0xe857cca5u, 0xaff7b675u, 0x92979fc5u,
0xe915e8dbu, 0xd475c16bu, 0x93d5bbbbu, 0xaeb5920bu, 0x1c954e1bu, 0x21f567abu, 0x66551d7bu, 0x5b3534cbu,
0xd965a31au, 0xe4058aaau, 0xa3a5f07au, 0x9ec5d9cau, 0x2ce505dau, 0x11852c6au, 0x562556bau, 0x6b457f0au,
0x89f57f59u, 0xb49556e9u, 0xf3352c39u, 0xce550589u, 0x7c75d999u, 0x4115f029u, 0x06b58af9u, 0x3bd5a349u,
0xb9853498u, 0x84e51d28u, 0xc34567f8u, 0xfe254e48u, 0x4c059258u, 0x7165bbe8u, 0x36c5c138u, 0x0ba5e888u,
0x28d4c7dfu, 0x15b4ee6fu, 0x521494bfu, 0x6f74bd0fu, 0xdd54611fu, 0xe03448afu, 0xa794327fu, 0x9af41bcfu,
0x18a48c1eu, 0x25c4a5aeu, 0x6264df7eu, 0x5f04f6ceu, 0xed242adeu, 0xd044036eu, 0x97e479beu, 0xaa84500eu,
0x4834505du, 0x755479edu, 0x32f4033du, 0x0f942a8du, 0xbdb4f69du, 0x80d4df2du, 0xc774a5fdu, 0xfa148c4du,
0x78441b9cu, 0x4524322cu, 0x028448fcu, 0x3fe4614cu, 0x8dc4bd5cu, 0xb0a494ecu, 0xf704ee3cu, 0xca64c78cu
};
static const unsigned lodepng_crc32_table5[256] = {
0x00000000u, 0xcb5cd3a5u, 0x4dc8a10bu, 0x869472aeu, 0x9b914216u, 0x50cd91b3u, 0xd659e31du, 0x1d0530b8u,
0xec53826du, 0x270f51c8u, 0xa19b2366u, 0x6ac7f0c3u, 0x77c2c07bu, 0xbc9e13deu, 0x3a0a6170u, 0xf156b2d5u,
0x03d6029bu, 0xc88ad13eu, 0x4e1ea390u, 0x85427035u, 0x9847408du, 0x531b9328u, 0xd58fe186u, 0x1ed33223u,
0xef8580f6u, 0x24d95353u, 0xa24d21fdu, 0x6911f258u, 0x7414c2e0u, 0xbf481145u, 0x39dc63ebu, 0xf280b04eu,
0x07ac0536u, 0xccf0d693u, 0x4a64a43du, 0x81387798u, 0x9c3d4720u, 0x57619485u, 0xd1f5e62bu, 0x1aa9358eu,
0xebff875bu, 0x20a354feu, 0xa6372650u, 0x6d6bf5f5u, 0x706ec54du, 0xbb3216e8u, 0x3da66446u, 0xf6fab7e3u,
0x047a07adu, 0xcf26d408u, 0x49b2a6a6u, 0x82ee7503u, 0x9feb45bbu, 0x54b7961eu, 0xd223e4b0u, 0x197f3715u,
0xe82985c0u, 0x23755665u, 0xa5e124cbu, 0x6ebdf76eu, 0x73b8c7d6u, 0xb8e41473u, 0x3e7066ddu, 0xf52cb578u,
0x0f580a6cu, 0xc404d9c9u, 0x4290ab67u, 0x89cc78c2u, 0x94c9487au, 0x5f959bdfu, 0xd901e971u, 0x125d3ad4u,
0xe30b8801u, 0x28575ba4u, 0xaec3290au, 0x659ffaafu, 0x789aca17u, 0xb3c619b2u, 0x35526b1cu, 0xfe0eb8b9u,
0x0c8e08f7u, 0xc7d2db52u, 0x4146a9fcu, 0x8a1a7a59u, 0x971f4ae1u, 0x5c439944u, 0xdad7ebeau, 0x118b384fu,
0xe0dd8a9au, 0x2b81593fu, 0xad152b91u, 0x6649f834u, 0x7b4cc88cu, 0xb0101b29u, 0x36846987u, 0xfdd8ba22u,
0x08f40f5au, 0xc3a8dcffu, 0x453cae51u, 0x8e607df4u, 0x93654d4cu, 0x58399ee9u, 0xdeadec47u, 0x15f13fe2u,
0xe4a78d37u, 0x2ffb5e92u, 0xa96f2c3cu, 0x6233ff99u, 0x7f36cf21u, 0xb46a1c84u, 0x32fe6e2au, 0xf9a2bd8fu,
0x0b220dc1u, 0xc07ede64u, 0x46eaaccau, 0x8db67f6fu, 0x90b34fd7u, 0x5bef9c72u, 0xdd7beedcu, 0x16273d79u,
0xe7718facu, 0x2c2d5c09u, 0xaab92ea7u, 0x61e5fd02u, 0x7ce0cdbau, 0xb7bc1e1fu, 0x31286cb1u, 0xfa74bf14u,
0x1eb014d8u, 0xd5ecc77du, 0x5378b5d3u, 0x98246676u, 0x852156ceu, 0x4e7d856bu, 0xc8e9f7c5u, 0x03b52460u,
0xf2e396b5u, 0x39bf4510u, 0xbf2b37beu, 0x7477e41bu, 0x6972d4a3u, 0xa22e0706u, 0x24ba75a8u, 0xefe6a60du,
0x1d661643u, 0xd63ac5e6u, 0x50aeb748u, 0x9bf264edu, 0x86f75455u, 0x4dab87f0u, 0xcb3ff55eu, 0x006326fbu,
0xf135942eu, 0x3a69478bu, 0xbcfd3525u, 0x77a1e680u, 0x6aa4d638u, 0xa1f8059du, 0x276c7733u, 0xec30a496u,
0x191c11eeu, 0xd240c24bu, 0x54d4b0e5u, 0x9f886340u, 0x828d53f8u, 0x49d1805du, 0xcf45f2f3u, 0x04192156u,
0xf54f9383u, 0x3e134026u, 0xb8873288u, 0x73dbe12du, 0x6eded195u, 0xa5820230u, 0x2316709eu, 0xe84aa33bu,
0x1aca1375u, 0xd196c0d0u, 0x5702b27eu, 0x9c5e61dbu, 0x815b5163u, 0x4a0782c6u, 0xcc93f068u, 0x07cf23cdu,
0xf6999118u, 0x3dc542bdu, 0xbb513013u, 0x700de3b6u, 0x6d08d30eu, 0xa65400abu, 0x20c07205u, 0xeb9ca1a0u,
0x11e81eb4u, 0xdab4cd11u, 0x5c20bfbfu, 0x977c6c1au, 0x8a795ca2u, 0x41258f07u, 0xc7b1fda9u, 0x0ced2e0cu,
0xfdbb9cd9u, 0x36e74f7cu, 0xb0733dd2u, 0x7b2fee77u, 0x662adecfu, 0xad760d6au, 0x2be27fc4u, 0xe0beac61u,
0x123e1c2fu, 0xd962cf8au, 0x5ff6bd24u, 0x94aa6e81u, 0x89af5e39u, 0x42f38d9cu, 0xc467ff32u, 0x0f3b2c97u,
0xfe6d9e42u, 0x35314de7u, 0xb3a53f49u, 0x78f9ececu, 0x65fcdc54u, 0xaea00ff1u, 0x28347d5fu, 0xe368aefau,
0x16441b82u, 0xdd18c827u, 0x5b8cba89u, 0x90d0692cu, 0x8dd55994u, 0x46898a31u, 0xc01df89fu, 0x0b412b3au,
0xfa1799efu, 0x314b4a4au, 0xb7df38e4u, 0x7c83eb41u, 0x6186dbf9u, 0xaada085cu, 0x2c4e7af2u, 0xe712a957u,
0x15921919u, 0xdececabcu, 0x585ab812u, 0x93066bb7u, 0x8e035b0fu, 0x455f88aau, 0xc3cbfa04u, 0x089729a1u,
0xf9c19b74u, 0x329d48d1u, 0xb4093a7fu, 0x7f55e9dau, 0x6250d962u, 0xa90c0ac7u, 0x2f987869u, 0xe4c4abccu
};
static const unsigned lodepng_crc32_table6[256] = {
0x00000000u, 0xa6770bb4u, 0x979f1129u, 0x31e81a9du, 0xf44f2413u, 0x52382fa7u, 0x63d0353au, 0xc5a73e8eu,
0x33ef4e67u, 0x959845d3u, 0xa4705f4eu, 0x020754fau, 0xc7a06a74u, 0x61d761c0u, 0x503f7b5du, 0xf64870e9u,
0x67de9cceu, 0xc1a9977au, 0xf0418de7u, 0x56368653u, 0x9391b8ddu, 0x35e6b369u, 0x040ea9f4u, 0xa279a240u,
0x5431d2a9u, 0xf246d91du, 0xc3aec380u, 0x65d9c834u, 0xa07ef6bau, 0x0609fd0eu, 0x37e1e793u, 0x9196ec27u,
0xcfbd399cu, 0x69ca3228u, 0x582228b5u, 0xfe552301u, 0x3bf21d8fu, 0x9d85163bu, 0xac6d0ca6u, 0x0a1a0712u,
0xfc5277fbu, 0x5a257c4fu, 0x6bcd66d2u, 0xcdba6d66u, 0x081d53e8u, 0xae6a585cu, 0x9f8242c1u, 0x39f54975u,
0xa863a552u, 0x0e14aee6u, 0x3ffcb47bu, 0x998bbfcfu, 0x5c2c8141u, 0xfa5b8af5u, 0xcbb39068u, 0x6dc49bdcu,
0x9b8ceb35u, 0x3dfbe081u, 0x0c13fa1cu, 0xaa64f1a8u, 0x6fc3cf26u, 0xc9b4c492u, 0xf85cde0fu, 0x5e2bd5bbu,
0x440b7579u, 0xe27c7ecdu, 0xd3946450u, 0x75e36fe4u, 0xb044516au, 0x16335adeu, 0x27db4043u, 0x81ac4bf7u,
0x77e43b1eu, 0xd19330aau, 0xe07b2a37u, 0x460c2183u, 0x83ab1f0du, 0x25dc14b9u, 0x14340e24u, 0xb2430590u,
0x23d5e9b7u, 0x85a2e203u, 0xb44af89eu, 0x123df32au, 0xd79acda4u, 0x71edc610u, 0x4005dc8du, 0xe672d739u,
0x103aa7d0u, 0xb64dac64u, 0x87a5b6f9u, 0x21d2bd4du, 0xe47583c3u, 0x42028877u, 0x73ea92eau, 0xd59d995eu,
0x8bb64ce5u, 0x2dc14751u, 0x1c295dccu, 0xba5e5678u, 0x7ff968f6u, 0xd98e6342u, 0xe86679dfu, 0x4e11726bu,
0xb8590282u, 0x1e2e0936u, 0x2fc613abu, 0x89b1181fu, 0x4c162691u, 0xea612d25u, 0xdb8937b8u, 0x7dfe3c0cu,
0xec68d02bu, 0x4a1fdb9fu, 0x7bf7c102u, 0xdd80cab6u, 0x1827f438u, 0xbe50ff8cu, 0x8fb8e511u, 0x29cfeea5u,
0xdf879e4cu, 0x79f095f8u, 0x48188f65u, 0xee6f84d1u, 0x2bc8ba5fu, 0x8dbfb1ebu, 0xbc57ab76u, 0x1a20a0c2u,
0x8816eaf2u, 0x2e61e146u, 0x1f89fbdbu, 0xb9fef06fu, 0x7c59cee1u, 0xda2ec555u, 0xebc6dfc8u, 0x4db1d47cu,
0xbbf9a495u, 0x1d8eaf21u, 0x2c66b5bcu, 0x8a11be08u, 0x4fb68086u, 0xe9c18b32u, 0xd82991afu, 0x7e5e9a1bu,
0xefc8763cu, 0x49bf7d88u, 0x78576715u, 0xde206ca1u, 0x1b87522fu, 0xbdf0599bu, 0x8c184306u, 0x2a6f48b2u,
0xdc27385bu, 0x7a5033efu, 0x4bb82972u, 0xedcf22c6u, 0x28681c48u, 0x8e1f17fcu, 0xbff70d61u, 0x198006d5u,
0x47abd36eu, 0xe1dcd8dau, 0xd034c247u, 0x7643c9f3u, 0xb3e4f77du, 0x1593fcc9u, 0x247be654u, 0x820cede0u,
0x74449d09u, 0xd23396bdu, 0xe3db8c20u, 0x45ac8794u, 0x800bb91au, 0x267cb2aeu, 0x1794a833u, 0xb1e3a387u,
0x20754fa0u, 0x86024414u, 0xb7ea5e89u, 0x119d553du, 0xd43a6bb3u, 0x724d6007u, 0x43a57a9au, 0xe5d2712eu,
0x139a01c7u, 0xb5ed0a73u, 0x840510eeu, 0x22721b5au, 0xe7d525d4u, 0x41a22e60u, 0x704a34fdu, 0xd63d3f49u,
0xcc1d9f8bu, 0x6a6a943fu, 0x5b828ea2u, 0xfdf58516u, 0x3852bb98u, 0x9e25b02cu, 0xafcdaab1u, 0x09baa105u,
0xfff2d1ecu, 0x5985da58u, 0x686dc0c5u, 0xce1acb71u, 0x0bbdf5ffu, 0xadcafe4bu, 0x9c22e4d6u, 0x3a55ef62u,
0xabc30345u, 0x0db408f1u, 0x3c5c126cu, 0x9a2b19d8u, 0x5f8c2756u, 0xf9fb2ce2u, 0xc813367fu, 0x6e643dcbu,
0x982c4d22u, 0x3e5b4696u, 0x0fb35c0bu, 0xa9c457bfu, 0x6c636931u, 0xca146285u, 0xfbfc7818u, 0x5d8b73acu,
0x03a0a617u, 0xa5d7ada3u, 0x943fb73eu, 0x3248bc8au, 0xf7ef8204u, 0x519889b0u, 0x6070932du, 0xc6079899u,
0x304fe870u, 0x9638e3c4u, 0xa7d0f959u, 0x01a7f2edu, 0xc400cc63u, 0x6277c7d7u, 0x539fdd4au, 0xf5e8d6feu,
0x647e3ad9u, 0xc209316du, 0xf3e12bf0u, 0x55962044u, 0x90311ecau, 0x3646157eu, 0x07ae0fe3u, 0xa1d90457u,
0x579174beu, 0xf1e67f0au, 0xc00e6597u, 0x66796e23u, 0xa3de50adu, 0x05a95b19u, 0x34414184u, 0x92364a30u
};
static const unsigned lodepng_crc32_table7[256] = {
0x00000000u, 0xccaa009eu, 0x4225077du, 0x8e8f07e3u, 0x844a0efau, 0x48e00e64u, 0xc66f0987u, 0x0ac50919u,
0xd3e51bb5u, 0x1f4f1b2bu, 0x91c01cc8u, 0x5d6a1c56u, 0x57af154fu, 0x9b0515d1u, 0x158a1232u, 0xd92012acu,
0x7cbb312bu, 0xb01131b5u, 0x3e9e3656u, 0xf23436c8u, 0xf8f13fd1u, 0x345b3f4fu, 0xbad438acu, 0x767e3832u,
0xaf5e2a9eu, 0x63f42a00u, 0xed7b2de3u, 0x21d12d7du, 0x2b142464u, 0xe7be24fau, 0x69312319u, 0xa59b2387u,
0xf9766256u, 0x35dc62c8u, 0xbb53652bu, 0x77f965b5u, 0x7d3c6cacu, 0xb1966c32u, 0x3f196bd1u, 0xf3b36b4fu,
0x2a9379e3u, 0xe639797du, 0x68b67e9eu, 0xa41c7e00u, 0xaed97719u, 0x62737787u, 0xecfc7064u, 0x205670fau,
0x85cd537du, 0x496753e3u, 0xc7e85400u, 0x0b42549eu, 0x01875d87u, 0xcd2d5d19u, 0x43a25afau, 0x8f085a64u,
0x562848c8u, 0x9a824856u, 0x140d4fb5u, 0xd8a74f2bu, 0xd2624632u, 0x1ec846acu, 0x9047414fu, 0x5ced41d1u,
0x299dc2edu, 0xe537c273u, 0x6bb8c590u, 0xa712c50eu, 0xadd7cc17u, 0x617dcc89u, 0xeff2cb6au, 0x2358cbf4u,
0xfa78d958u, 0x36d2d9c6u, 0xb85dde25u, 0x74f7debbu, 0x7e32d7a2u, 0xb298d73cu, 0x3c17d0dfu, 0xf0bdd041u,
0x5526f3c6u, 0x998cf358u, 0x1703f4bbu, 0xdba9f425u, 0xd16cfd3cu, 0x1dc6fda2u, 0x9349fa41u, 0x5fe3fadfu,
0x86c3e873u, 0x4a69e8edu, 0xc4e6ef0eu, 0x084cef90u, 0x0289e689u, 0xce23e617u, 0x40ace1f4u, 0x8c06e16au,
0xd0eba0bbu, 0x1c41a025u, 0x92cea7c6u, 0x5e64a758u, 0x54a1ae41u, 0x980baedfu, 0x1684a93cu, 0xda2ea9a2u,
0x030ebb0eu, 0xcfa4bb90u, 0x412bbc73u, 0x8d81bcedu, 0x8744b5f4u, 0x4beeb56au, 0xc561b289u, 0x09cbb217u,
0xac509190u, 0x60fa910eu, 0xee7596edu, 0x22df9673u, 0x281a9f6au, 0xe4b09ff4u, 0x6a3f9817u, 0xa6959889u,
0x7fb58a25u, 0xb31f8abbu, 0x3d908d58u, 0xf13a8dc6u, 0xfbff84dfu, 0x37558441u, 0xb9da83a2u, 0x7570833cu,
0x533b85dau, 0x9f918544u, 0x111e82a7u, 0xddb48239u, 0xd7718b20u, 0x1bdb8bbeu, 0x95548c5du, 0x59fe8cc3u,
0x80de9e6fu, 0x4c749ef1u, 0xc2fb9912u, 0x0e51998cu, 0x04949095u, 0xc83e900bu, 0x46b197e8u, 0x8a1b9776u,
0x2f80b4f1u, 0xe32ab46fu, 0x6da5b38cu, 0xa10fb312u, 0xabcaba0bu, 0x6760ba95u, 0xe9efbd76u, 0x2545bde8u,
0xfc65af44u, 0x30cfafdau, 0xbe40a839u, 0x72eaa8a7u, 0x782fa1beu, 0xb485a120u, 0x3a0aa6c3u, 0xf6a0a65du,
0xaa4de78cu, 0x66e7e712u, 0xe868e0f1u, 0x24c2e06fu, 0x2e07e976u, 0xe2ade9e8u, 0x6c22ee0bu, 0xa088ee95u,
0x79a8fc39u, 0xb502fca7u, 0x3b8dfb44u, 0xf727fbdau, 0xfde2f2c3u, 0x3148f25du, 0xbfc7f5beu, 0x736df520u,
0xd6f6d6a7u, 0x1a5cd639u, 0x94d3d1dau, 0x5879d144u, 0x52bcd85du, 0x9e16d8c3u, 0x1099df20u, 0xdc33dfbeu,
0x0513cd12u, 0xc9b9cd8cu, 0x4736ca6fu, 0x8b9ccaf1u, 0x8159c3e8u, 0x4df3c376u, 0xc37cc495u, 0x0fd6c40bu,
0x7aa64737u, 0xb60c47a9u, 0x3883404au, 0xf42940d4u, 0xfeec49cdu, 0x32464953u, 0xbcc94eb0u, 0x70634e2eu,
0xa9435c82u, 0x65e95c1cu, 0xeb665bffu, 0x27cc5b61u, 0x2d095278u, 0xe1a352e6u, 0x6f2c5505u, 0xa386559bu,
0x061d761cu, 0xcab77682u, 0x44387161u, 0x889271ffu, 0x825778e6u, 0x4efd7878u, 0xc0727f9bu, 0x0cd87f05u,
0xd5f86da9u, 0x19526d37u, 0x97dd6ad4u, 0x5b776a4au, 0x51b26353u, 0x9d1863cdu, 0x1397642eu, 0xdf3d64b0u,
0x83d02561u, 0x4f7a25ffu, 0xc1f5221cu, 0x0d5f2282u, 0x079a2b9bu, 0xcb302b05u, 0x45bf2ce6u, 0x89152c78u,
0x50353ed4u, 0x9c9f3e4au, 0x121039a9u, 0xdeba3937u, 0xd47f302eu, 0x18d530b0u, 0x965a3753u, 0x5af037cdu,
0xff6b144au, 0x33c114d4u, 0xbd4e1337u, 0x71e413a9u, 0x7b211ab0u, 0xb78b1a2eu, 0x39041dcdu, 0xf5ae1d53u,
0x2c8e0fffu, 0xe0240f61u, 0x6eab0882u, 0xa201081cu, 0xa8c40105u, 0x646e019bu, 0xeae10678u, 0x264b06e6u
};
/* Computes the cyclic redundancy check as used by PNG chunks*/
unsigned lodepng_crc32(const unsigned char* data, size_t length) {
/*Using the Slicing by Eight algorithm*/
unsigned r = 0xffffffffu;
size_t i;
for(i = 0; i < length; ++i) {
r = lodepng_crc32_table[(r ^ data[i]) & 0xffu] ^ (r >> 8u);
while(length >= 8) {
r = lodepng_crc32_table7[(data[0] ^ (r & 0xffu))] ^
lodepng_crc32_table6[(data[1] ^ ((r >> 8) & 0xffu))] ^
lodepng_crc32_table5[(data[2] ^ ((r >> 16) & 0xffu))] ^
lodepng_crc32_table4[(data[3] ^ ((r >> 24) & 0xffu))] ^
lodepng_crc32_table3[data[4]] ^
lodepng_crc32_table2[data[5]] ^
lodepng_crc32_table1[data[6]] ^
lodepng_crc32_table0[data[7]];
data += 8;
length -= 8;
}
while(length--) {
r = lodepng_crc32_table0[(r ^ *data++) & 0xffu] ^ (r >> 8);
}
return r ^ 0xffffffffu;
}
#else /* LODEPNG_COMPILE_CRC */
/*in this case, the function is only declared here, and must be defined externally
so that it will be linked in*/
so that it will be linked in.
Example implementation that uses a much smaller lookup table for memory constrained cases:
unsigned lodepng_crc32(const unsigned char* data, size_t length) {
unsigned r = 0xffffffffu;
static const unsigned table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
while(length--) {
r = table[(r ^ *data) & 0xf] ^ (r >> 4);
r = table[(r ^ (*data >> 4)) & 0xf] ^ (r >> 4);
data++;
}
return r ^ 0xffffffffu;
}
*/
unsigned lodepng_crc32(const unsigned char* data, size_t length);
#endif /* LODEPNG_COMPILE_CRC */
@ -3964,15 +4237,14 @@ static unsigned auto_choose_color(LodePNGColorMode* mode_out,
#endif /* #ifdef LODEPNG_COMPILE_ENCODER */
/*
Paeth predictor, used by PNG filter type 4
The parameters are of type short, but should come from unsigned chars, the shorts
are only needed to make the paeth calculation correct.
*/
static unsigned char paethPredictor(short a, short b, short c) {
short pa = LODEPNG_ABS(b - c);
short pb = LODEPNG_ABS(a - c);
short pc = LODEPNG_ABS(a + b - c - c);
/*Paeth predictor, used by PNG filter type 4*/
static unsigned char paethPredictor(unsigned char a, unsigned char b, unsigned char c) {
/* the subtractions of unsigned char cast it to a signed type.
With gcc, short is faster than int, with clang int is as fast (as of april 2023)*/
short pa = (b - c) < 0 ? -(b - c) : (b - c);
short pb = (a - c) < 0 ? -(a - c) : (a - c);
/* writing it out like this compiles to something faster than introducing a temp variable*/
short pc = (a + b - c - c) < 0 ? -(a + b - c - c) : (a + b - c - c);
/* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */
if(pb < pa) { a = b; pa = pb; }
return (pc < pa) ? c : a;
@ -4168,47 +4440,108 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
break;
case 4:
if(precon) {
size_t j = 0;
for(i = 0; i != bytewidth; ++i) {
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
}
/* Unroll independent paths of the paeth predictor. A 6x and 8x version is also possible but that
adds too much code. Whether this speeds up anything depends on compiler and settings. */
if(bytewidth >= 4) {
for(; i + 3 < length; i += 4, j += 4) {
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3];
recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
/* Unroll independent paths of this predictor. Whether this speeds up
anything depends on compiler and settings. */
if(bytewidth == 8) {
unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0;
unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0;
unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0;
unsigned char a6, b6 = 0, c6, d6 = 0, a7, b7 = 0, c7, d7 = 0;
for(i = 0; i + 7 < length; i += 8) {
c0 = b0; c1 = b1; c2 = b2; c3 = b3;
c4 = b4; c5 = b5; c6 = b6; c7 = b7;
b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3];
b4 = precon[i + 4]; b5 = precon[i + 5]; b6 = precon[i + 6]; b7 = precon[i + 7];
a0 = d0; a1 = d1; a2 = d2; a3 = d3;
a4 = d4; a5 = d5; a6 = d6; a7 = d7;
d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
d2 = scanline[i + 2] + paethPredictor(a2, b2, c2);
d3 = scanline[i + 3] + paethPredictor(a3, b3, c3);
d4 = scanline[i + 4] + paethPredictor(a4, b4, c4);
d5 = scanline[i + 5] + paethPredictor(a5, b5, c5);
d6 = scanline[i + 6] + paethPredictor(a6, b6, c6);
d7 = scanline[i + 7] + paethPredictor(a7, b7, c7);
recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3;
recon[i + 4] = d4; recon[i + 5] = d5; recon[i + 6] = d6; recon[i + 7] = d7;
}
} else if(bytewidth >= 3) {
for(; i + 2 < length; i += 3, j += 3) {
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2];
recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
} else if(bytewidth == 6) {
unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0;
unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0;
unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0;
for(i = 0; i + 5 < length; i += 6) {
c0 = b0; c1 = b1; c2 = b2;
c3 = b3; c4 = b4; c5 = b5;
b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2];
b3 = precon[i + 3]; b4 = precon[i + 4]; b5 = precon[i + 5];
a0 = d0; a1 = d1; a2 = d2;
a3 = d3; a4 = d4; a5 = d5;
d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
d2 = scanline[i + 2] + paethPredictor(a2, b2, c2);
d3 = scanline[i + 3] + paethPredictor(a3, b3, c3);
d4 = scanline[i + 4] + paethPredictor(a4, b4, c4);
d5 = scanline[i + 5] + paethPredictor(a5, b5, c5);
recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2;
recon[i + 3] = d3; recon[i + 4] = d4; recon[i + 5] = d5;
}
} else if(bytewidth >= 2) {
for(; i + 1 < length; i += 2, j += 2) {
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
unsigned char q0 = precon[j + 0], q1 = precon[j + 1];
recon[i + 0] = s0 + paethPredictor(r0, p0, q0);
recon[i + 1] = s1 + paethPredictor(r1, p1, q1);
} else if(bytewidth == 4) {
unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0;
unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0;
for(i = 0; i + 3 < length; i += 4) {
c0 = b0; c1 = b1; c2 = b2; c3 = b3;
b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3];
a0 = d0; a1 = d1; a2 = d2; a3 = d3;
d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
d2 = scanline[i + 2] + paethPredictor(a2, b2, c2);
d3 = scanline[i + 3] + paethPredictor(a3, b3, c3);
recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2; recon[i + 3] = d3;
}
} else if(bytewidth == 3) {
unsigned char a0, b0 = 0, c0, d0 = 0;
unsigned char a1, b1 = 0, c1, d1 = 0;
unsigned char a2, b2 = 0, c2, d2 = 0;
for(i = 0; i + 2 < length; i += 3) {
c0 = b0; c1 = b1; c2 = b2;
b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2];
a0 = d0; a1 = d1; a2 = d2;
d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
d2 = scanline[i + 2] + paethPredictor(a2, b2, c2);
recon[i + 0] = d0; recon[i + 1] = d1; recon[i + 2] = d2;
}
} else if(bytewidth == 2) {
unsigned char a0, b0 = 0, c0, d0 = 0;
unsigned char a1, b1 = 0, c1, d1 = 0;
for(i = 0; i + 1 < length; i += 2) {
c0 = b0; c1 = b1;
b0 = precon[i + 0];
b1 = precon[i + 1];
a0 = d0; a1 = d1;
d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
recon[i + 0] = d0;
recon[i + 1] = d1;
}
} else if(bytewidth == 1) {
unsigned char a, b = 0, c, d = 0;
for(i = 0; i != length; ++i) {
c = b;
b = precon[i];
a = d;
d = scanline[i] + paethPredictor(a, b, c);
recon[i] = d;
}
} else {
/* Normally not a possible case, but this would handle it correctly */
for(i = 0; i != bytewidth; ++i) {
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
}
}
for(; i != length; ++i, ++j) {
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[j]));
/* finish any remaining bytes */
for(; i != length; ++i) {
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
}
} else {
size_t j = 0;

View file

@ -1,7 +1,7 @@
/*
LodePNG version 20220717
LodePNG version 20230410
Copyright (c) 2005-2022 Lode Vandevenne
Copyright (c) 2005-2023 Lode Vandevenne
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -92,7 +92,10 @@ or comment out LODEPNG_COMPILE_ALLOCATORS below*/
#endif
/*Disable built-in CRC function, in that case a custom implementation of
lodepng_crc32 must be defined externally so that it can be linked in.*/
lodepng_crc32 must be defined externally so that it can be linked in.
The default built-in CRC code comes with 8KB of lookup tables, so for memory constrained environment you may want it
disabled and provide a much smaller implementation externally as said above. You can find such an example implementation
in a comment in the lodepng.c(pp) file in the 'else' case of the searchable LODEPNG_COMPILE_CRC section.*/
#ifndef LODEPNG_NO_COMPILE_CRC
/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one,
or comment out LODEPNG_COMPILE_CRC below*/
@ -1909,6 +1912,7 @@ symbol.
Not all changes are listed here, the commit history in github lists more:
https://github.com/lvandeve/lodepng
*) 10 apr 2023: faster CRC32 implementation, but with larger lookup table.
*) 13 jun 2022: added support for the sBIT chunk.
*) 09 jan 2022: minor decoder speed improvements.
*) 27 jun 2021: added warnings that file reading/writing functions don't support

View file

@ -33,17 +33,6 @@ BYTE disp = 0; // flag for update display area
static LPBYTE pbyRomView[2] = {NULL, NULL}; // HP49G ROM views
// CRC calculation
static WORD crc_table[] =
{
0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F
};
static __inline VOID UpCRC(BYTE nib)
{
Chipset.crc = (WORD)((Chipset.crc>>4)^crc_table[(Chipset.crc^nib)&0xf]);
}
static __inline UINT MIN(UINT a, UINT b)
{
return (a<b)?a:b;
@ -783,7 +772,11 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
ReadIO(a,v,c,TRUE);
// reading MSB of timer2 update the CRC register
if (v+c == 0x40) UpCRC(a[c-1]); // timer2 MSB touched, update the CRC register
if (v+c == 0x40) // timer2 MSB touched
{
// update the CRC register
Chipset.crc = UpCRC(Chipset.crc,a[c-1]);
}
}
else
{
@ -849,7 +842,7 @@ VOID Nread(BYTE *a, DWORD d, UINT s)
}
for (u=0; u<c; u++) // update CRC
UpCRC(a[u]);
Chipset.crc = UpCRC(Chipset.crc,a[u]);
}
a+=c;
d=(d+c)&0xFFFFF;
@ -1145,6 +1138,22 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate)
break;
case 0x12: // TCS
*a = Chipset.IORam[d]; // return TCS value
if ((*a & TBF)) // Transmit buffer full
{
// the G-series XModem implementation has a timeout loop counter
// waiting for transmit buffer empty, so on fast hosts with
// CPU running with max. speed we may get a timeout overflow
// -> to avoid this slow down CPU speed on transmit buffer full
InitAdjustSpeed(); // init variables if necessary
EnterCriticalSection(&csSlowLock);
{
nOpcSlow = 10; // slow down next 10 opcodes
}
LeaveCriticalSection(&csSlowLock);
}
#if defined DEBUG_SERIAL
if (bUpdate)
{

View file

@ -61,6 +61,24 @@ typedef ULONG ULONG_PTR, *PULONG_PTR;
typedef LONG LONG_PTR, *PLONG_PTR;
#endif
#if !defined PROCESS_POWER_THROTTLING_CURRENT_VERSION
#define PROCESS_POWER_THROTTLING_CURRENT_VERSION 1
#endif
#if !defined PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION
#define PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION 0x04
#endif
#if _MSC_VER <= 1900 // add until VS2015 from processthreadsapi.h
enum { ProcessPowerThrottling = 4 };
typedef struct _PROCESS_POWER_THROTTLING_STATE {
ULONG Version;
ULONG ControlMask;
ULONG StateMask;
} PROCESS_POWER_THROTTLING_STATE, * PPROCESS_POWER_THROTTLING_STATE;
#endif
#if _MSC_VER >= 1400 // valid for VS2005 and later
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\" \

57
source/PNGCRC.C Normal file
View file

@ -0,0 +1,57 @@
/*
* pngcrc.c
*
* This file is part of Emu48
*
* Copyright (C) 2023 Christoph Gießelink
*
*/
#include "pch.h"
/* CRC polynomial: 0xedb88320 */
static const unsigned lodepng_crc32_table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
/*Return the CRC of the bytes buf[0..len-1].*/
unsigned lodepng_crc32(const unsigned char* data, size_t length)
{
unsigned r = 0xffffffffu;
while (length--)
{
r = lodepng_crc32_table[(r ^ *data++) & 0xffu] ^ (r >> 8u);
}
return ~r;
}

250
source/ROMCRC.C Normal file
View file

@ -0,0 +1,250 @@
/*
* romcrc.c
*
* This file is part of Emu48
*
* Copyright (C) 2022 Christoph Gießelink
*
*/
#include "pch.h"
#include "Emu48.h"
#include "ops.h"
// flash page types
#define BOOT 0x86
#define FS 0x18
#define SYSTEM 0x32
#define ROM 0x0F
#define RAM 0xF0
//################
//#
//# Restore HP38G/HP48GX/SX ROM CRC
//#
//################
// Clarke/Yorke CRC for HP38G and HP48GX/SX
#define a0 0x0 // Start Address
#define d0 (n0*16) // Address offset
#define n0 0x4000 // Reads/Half-Sector
#define s0 1 // #Sectors (Sector Size=2*d)
// rebuild of the calculator =CHECKSUM function for the Clarke and the Yorke chip ROM
static WORD Checksum(LPBYTE pbyROM, DWORD dwStart, DWORD dwOffset, INT nReads, INT nSector)
{
int i,j;
WORD wCrc = 0;
for (;nSector > 0; --nSector) // evaluate each sector
{
LPBYTE pbyAddr1 = pbyROM + dwStart;
LPBYTE pbyAddr2 = pbyAddr1 + dwOffset;
for (i = 0; i < nReads; ++i) // no. of reads in sector
{
for (j = 0; j < 16; ++j) wCrc = UpCRC(wCrc,*pbyAddr1++);
for (j = 0; j < 16; ++j) wCrc = UpCRC(wCrc,*pbyAddr2++);
}
dwStart += 2 * dwOffset; // next start page
}
return wCrc;
}
// calculate proper checksum to produce final CRC of FFFF
static __inline WORD CalcChksum(WORD wCrc, WORD wChksum)
{
WORD q, r = wCrc, s = wChksum;
// first take the last 4-nib back out of the CRC
r = (((r >> 12) * 0x811) ^ (r << 4) ^ (s & 0xf));
s >>= 4;
r = (((r >> 12) * 0x811) ^ (r << 4) ^ (s & 0xf));
s >>= 4;
r = (((r >> 12) * 0x811) ^ (r << 4) ^ (s & 0xf));
s >>= 4;
r = (((r >> 12) * 0x811) ^ (r << 4) ^ (s & 0xf));
// calculate new checksum to correct the CRC
s = 0xf831; // required MSNs to make goal
q = (q<<4) | ((r ^ s) & 0xf); // get 1st (least sig) nib
r = (r>>4) ^ ((s & 0xf) * 0x1081);
s >>= 4;
q = (q<<4) | ((r ^ s) & 0xf);
r = (r>>4) ^ ((s & 0xf) * 0x1081);
s >>= 4;
q = (q<<4) | ((r ^ s) & 0xf);
r = (r>>4) ^ ((s & 0xf) * 0x1081);
s >>= 4;
q = (q<<4) | ((r ^ s) & 0xf);
return q;
}
static VOID CorrectCrc(DWORD dwAddrCrc, WORD wCrc)
{
if (wCrc != 0xFFFF) // wrong crc result
{
INT s;
// get actual crc correction value
const WORD wChkAct = (pbyRom[dwAddrCrc+0] << 12)
| (pbyRom[dwAddrCrc+1] << 8)
| (pbyRom[dwAddrCrc+2] << 4)
| (pbyRom[dwAddrCrc+3]);
wCrc = CalcChksum(wCrc,wChkAct); // calculate new checksum
for (s = 3; s >= 0; --s) // write new checksum
{
PatchNibble(dwAddrCrc + s,(BYTE) (wCrc & 0xf));
wCrc >>= 4;
}
}
return;
}
//################
//#
//# Restore HP49G ROM CRC
//#
//################
static VOID CorrectFlashCrc(LPBYTE pbyMem, DWORD dwSize, DWORD dwOffset, DWORD dwLength)
{
// address overflow (data length + 4 nibble CRC)
if (dwOffset + dwLength + 4 <= dwSize)
{
WORD wRefCrc,wCrc = 0;
pbyMem += dwOffset; // start address
for (; dwLength > 0; --dwLength) // update CRC
{
wCrc = UpCRC(wCrc,*pbyMem++);
}
wRefCrc = (WORD) Npack(pbyMem,4); // read reference CRC
if(wRefCrc != wCrc) // wrong page CRC
{
INT s;
// linear CRC address in ROM
DWORD dwAddrCrc = (DWORD) (pbyMem - pbyRom);
wRefCrc = wCrc; // working copy of CRC
for (s = 0; s < 4; ++s) // write new checksum
{
PatchNibble(dwAddrCrc++,(BYTE) (wRefCrc & 0xf));
wRefCrc >>= 4;
}
_ASSERT(wCrc == (WORD) Npack(pbyMem,4));
}
}
return;
}
static __inline VOID CorrectFlashRom(LPBYTE pbyMem, DWORD dwSize)
{
CorrectFlashCrc(pbyMem,dwSize,0x20A,Npack(pbyMem+0x20A,5));
return;
}
static __inline VOID CorrectFlashSystem(LPBYTE pbyMem, DWORD dwSize)
{
CorrectFlashCrc(pbyMem,dwSize,0x20A,Npack(pbyMem+0x100,5));
return;
}
static __inline VOID CorrectFlashPage(LPBYTE pbyMem, DWORD dwSize, DWORD dwPage)
{
_ASSERT(dwPage >= 0 && dwPage < 16);
dwPage *= _KB(128); // convert page no. to data offset
if (dwPage + _KB(128) <= dwSize) // page inside flash chip
{
BYTE byType;
pbyMem += dwPage; // page address
dwPage = _KB(128); // page size
// get bank type
byType = (BYTE) Npack(pbyMem+0x200,2);
if (byType == BOOT) // 1st half of page is the boot bank
{
pbyMem += _KB(64); // 2nd half of page
dwPage = _KB(64); // page size
// get bank type
byType = (BYTE) Npack(pbyMem+0x200,2);
}
_ASSERT(dwPage == _KB(64) || dwPage == _KB(128));
switch (byType)
{
case FS: // FRBankFileSystem
case ROM: // FRBankRom
CorrectFlashRom(pbyMem,dwPage);
break;
case SYSTEM: // FRBankSystem
CorrectFlashSystem(pbyMem,dwPage);
break;
case RAM: // FRBankRam
default: // illegal bank identifier
break;
}
}
return;
}
static __inline VOID CorrectAllFlashPages(VOID)
{
DWORD dwPage;
// check CRC of all pages
CONST DWORD dwLastPage = dwRomSize / _KB(128);
for (dwPage = 0; dwPage < dwLastPage; ++dwPage)
{
// correct CRC of page
CorrectFlashPage(pbyRom,dwRomSize,dwPage);
}
return;
}
//################
//#
//# Restore ROM CRC
//#
//################
VOID RebuildRomCrc(VOID)
{
// HP38G, HP48GX, HP48SX
if ((strchr("6AGS",cCurrentRomType)) && dwRomSize >= _KB(256))
{
// first 256KB
CorrectCrc(0x7FFFC,Checksum(pbyRom,a0,d0,n0,s0));
}
// HP38G, HP48GX
if ((strchr("6AG",cCurrentRomType)) && dwRomSize == _KB(512))
{
// second 256KB
CorrectCrc(0xFFFFC,Checksum(pbyRom,a0+_KB(256),d0,n0,s0));
}
// HP39G/40G
if (cCurrentRomType == 'E')
{
// has no Crc
}
// HP49G
if (cCurrentRomType == 'X' && dwRomSize == _KB(2048))
{
CorrectAllFlashPages(); // go through all pages
}
return;
}

View file

@ -107,6 +107,8 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
_ASSERT(Chipset.IORam[IOC] & SON); // UART on
CommClose(); // close port if already open
dwBytesRead = 0L; // no bytes received
if (lstrcmp(strPort, _T(NO_SERIAL))) // port defined
{
TCHAR szDevice[256] = _T("\\\\.\\");
@ -130,7 +132,6 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
DWORD dwThreadId;
nRp = 0; // reset receiver state
dwBytesRead = 0L;
SetCommTimeouts(hComm,&CommTimeouts);
CommSetBaud();
@ -157,7 +158,9 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort)
while (!bReading) Sleep(0); // wait for SerialThread started
}
else
{
hComm = NULL;
}
}
#if defined DEBUG_SERIAL
@ -356,12 +359,23 @@ VOID CommReceive(VOID)
break;
// reject reading if com port is closed and not whole operation
if (hComm && dwBytesRead == 0L) // com port open and buffer empty
if (hComm) // com port open
{
if (ReadFile(hComm,cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
dwBytesRead = 0L;
else // bytes received
nRp = 0; // reset read pointer
UINT uCnt = 0; // retry counter
while (dwBytesRead == 0L) // buffer empty
{
if (ReadFile(hComm,cBuffer,sizeof(cBuffer),&dwBytesRead,&os) == FALSE)
dwBytesRead = 0L;
else // bytes received
nRp = 0; // reset read pointer
// something received or passed 1st retry
if (dwBytesRead != 0L || ++uCnt > 1)
break; // quit
Sleep(1); // workaround, retry 1ms later
}
}
if (dwBytesRead == 0L) // receive buffer empty

View file

@ -10,27 +10,27 @@
#include "Emu48.h"
TCHAR szUdpServer[1024] = _T("localhost");
WORD wUdpPort = 5025; // scpi-raw
WORD wUdpPort = 5025; // scpi-raw
static IN_ADDR ip_addr = { 255, 255, 255, 255 };
static SOCKADDR_IN sServer = { AF_INET, 0, { 255, 255, 255, 255 } };
VOID ResetUdp(VOID)
{
ip_addr.s_addr = INADDR_NONE; // invalidate saved UDP address
sServer.sin_addr.s_addr = INADDR_NONE; // invalidate saved UDP address
return;
}
BOOL SendByteUdp(BYTE byData)
{
WSADATA wsd;
SOCKET sClient;
SOCKADDR_IN sServer;
WSADATA wsd;
SOCKET sClient;
BOOL bErr = TRUE;
VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0);
if (ip_addr.s_addr == INADDR_NONE) // IP address not specified
// IP address not specified
if (sServer.sin_addr.s_addr == INADDR_NONE)
{
LPSTR lpszIpAddr;
@ -38,7 +38,7 @@ BOOL SendByteUdp(BYTE byData)
DWORD dwLength = lstrlen(szUdpServer) + 1;
if ((lpszIpAddr = (LPSTR) _alloca(dwLength)) == NULL)
return TRUE; // server not found
return TRUE; // server ip address not found
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
szUdpServer, dwLength,
@ -47,27 +47,26 @@ BOOL SendByteUdp(BYTE byData)
lpszIpAddr = szUdpServer;
#endif
ip_addr.s_addr = inet_addr(lpszIpAddr);
// try to interpret string as IPv4 address
sServer.sin_addr.s_addr = inet_addr(lpszIpAddr);
// not a valid ip address -> try to get ip address from name server
if (ip_addr.s_addr == INADDR_NONE)
if (sServer.sin_addr.s_addr == INADDR_NONE)
{
PHOSTENT host = gethostbyname(lpszIpAddr);
if (host == NULL)
{
return TRUE; // server not found
return TRUE; // server ip address not found
}
ip_addr.s_addr = ((PIN_ADDR) host->h_addr_list[0])->s_addr;
sServer.sin_addr.s_addr = ((PIN_ADDR) host->h_addr_list[0])->s_addr;
}
}
// create UDP socket
if ((sClient = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET)
{
sServer.sin_family = AF_INET;
sServer.sin_port = htons(wUdpPort);
sServer.sin_addr.s_addr = ip_addr.s_addr;
// transmit data byte
bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR;