diff --git a/Emu48.exe b/Emu48.exe index 2b021a5..0b79d1a 100755 Binary files a/Emu48.exe and b/Emu48.exe differ diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT index d1b45b6..f4913cc 100644 --- a/PROBLEMS.TXT +++ b/PROBLEMS.TXT @@ -1,4 +1,4 @@ -Known bugs and restrictions of Emu48 V1.65 +Known bugs and restrictions of Emu48 V1.66 ------------------------------------------ - the following I/O bits aren't emulated (incomplete) @@ -47,4 +47,4 @@ Known bugs and restrictions of Emu48 V1.65 - quitting the emulator while programming the flash isn't allowed, because the content of flash state machine isn't saved so far -07/26/22 (c) by Christoph Gießelink, c dot giesselink at gmx dot de +06/20/23 (c) by Christoph Gießelink, c dot giesselink at gmx dot de diff --git a/Sources/Emu48/CHANGES.TXT b/Sources/Emu48/CHANGES.TXT index dab5a6f..c30f61a 100644 --- a/Sources/Emu48/CHANGES.TXT +++ b/Sources/Emu48/CHANGES.TXT @@ -1,3 +1,105 @@ +Service Pack 66 for Emu48 Version 1.0 + +DISRPL.C +- changed function PutSn(), BINx(), DoSemiStream(), + RplDecodeObject() and RplCreateObjView(), added error handling for + memory allocation failed + +EMU48.C +- changed function WinMain(), added disable of TIMER_RESOLUTION + throttling for Windows 11 and added a more flexible CPU binding + for the Saturn core emulation thread on Windows Vista and later + with function GetCurrentProcessorNumber() + +EMU48.H +- added _KB definition +- changed function prototypes +- extern declaration of global variable and functions +- removed extern declaration of global function +- added inline function UpCRC(), new implementation as inline + function using a polynomial multiplication instead of the earlier + polynomial table solution which is faster on host CPUs with a + hardware integer multiplication unit + +EMU48.DSP +- added romcrc.c and pngcrc.c sources +- added "LODEPNG_NO_COMPILE_CRC" to lodepng.c definitions + +EMU48.RC +- changed version and copyright + +FILES.C +- added global variable for ROM CRC correction +- changed pbySignatureA[], pbySignatureB[], pbySignatureE[], + pbySignatureW[] and pbySignatureV[] to the byte pointer array + bySignature[] and defined signatures as constant +- changed function PatchRom(), made function public and set flag to + correct the ROM CRC +- changed function MapRom() and UnmapRom(), speed optimization + unpacking/packing ROM image and added reset of ROM patch flag +- changed function CrcPort2(), made function public, optimized + memory access and replaced CRC formula by call of function UpCRC() +- changed function NewDocument(), SaveBackup(), RestoreBackup() and + CreateRgnFromBitmap(), added error handling for memory allocation + failed +- changed function OpenDocument(), simplified file signature check +- changed function SaveDocument(), adjusted to bySignatureE[] + +KML.C +- changed function AddToLog(), optimized implementation +- changed function DestroyKmlList(), minor optimization +- changed function CreateKmlList(), added error handling for memory + allocation failed +- changed function ParseString(), optimized memory allocation and + added error handling for memory allocation failed +- changed function ParseLine(), ParseLines() and ParseBlock(), + added error handling for memory allocation failed +- changed function InitKML(), added rebuild of ROM CRC after ROM + patches + +LODEPNG.C +- changed implementation file to LodePNG version 20230410 with + unmarked typecast patches for x64 compatibility, Copyright (c) + 2005-2023 Lode Vandevenne + +LODEPNG.H +- changed header file to LodePNG version 20230410 + +MOPS.C +- moved function UpCRC() with a new function prototype and + implementation to EMU48.H +- changed function Nread(), adjusted to he new prototype of function + UpCRC() +- changed function ReadIO(), added CPU slow down for the TBF bit in + the TCS (0x112) register as workaround for the HP48G-series + transmit buffer full timeout overflow in the XSEND command and the + software derivations base on this source code + +PCH.H +- added definitions, emum and struct for calling function + SetProcessInformation() + +PNGCRC.C +- new module for generating the PNG CRC32 replacing the CRC + generation in LODEPNG.C + +ROMCRC.C +- new module correcting the ROM CRC after a ROM patch + +SERIAL.C +- bugfix in function CommOpen(), global variable dwBytesRead wasn't + initialized with 0 in all cases +- bugfix in function CommReceive(), added workaround for ReadFile() + timeouts to get "Library 1275: XYMODEM v3.2 for S/G" working + +UDP.C +- replaced static IN_ADDR by SOCKADDR_IN structure +- changed function ResetUdp(), invalidate IP address inside + SOCKADDR_IN structure +- changed function SendByteUdp(), replaced local SOCKADDR_IN + by the global static SOCKADDR_IN structure + + Service Pack 65 for Emu48 Version 1.0 EMU48.C diff --git a/Sources/Emu48/DISRPL.C b/Sources/Emu48/DISRPL.C index 3120b53..494eae8 100644 --- a/Sources/Emu48/DISRPL.C +++ b/Sources/Emu48/DISRPL.C @@ -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; } diff --git a/Sources/Emu48/EMU48.C b/Sources/Emu48/EMU48.C index 7af76f8..37419d5 100644 --- a/Sources/Emu48/EMU48.C +++ b/Sources/Emu48/EMU48.C @@ -13,7 +13,7 @@ #include "kml.h" #include "debugger.h" -#define VERSION "1.65" +#define VERSION "1.66" #ifdef _DEBUG LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug"); @@ -2031,19 +2031,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); @@ -2136,6 +2136,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; @@ -2186,15 +2206,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 diff --git a/Sources/Emu48/EMU48.DSP b/Sources/Emu48/EMU48.DSP index b1d8f13..3fc3065 100644 --- a/Sources/Emu48/EMU48.DSP +++ b/Sources/Emu48/EMU48.DSP @@ -216,7 +216,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 @@ -242,10 +242,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 diff --git a/Sources/Emu48/EMU48.H b/Sources/Emu48/EMU48.H index 570e62c..2bdd35f 100644 --- a/Sources/Emu48/EMU48.H +++ b/Sources/Emu48/EMU48.H @@ -8,6 +8,8 @@ */ #include "types.h" +#define _KB(a) ((a)*2*1024) + #define HARDWARE "Yorke" // emulator hardware #define MODELS "6AEGSX" // valid calculator models @@ -73,6 +75,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; @@ -250,6 +255,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; @@ -261,12 +267,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); @@ -289,6 +295,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); diff --git a/Sources/Emu48/EMU48.RC b/Sources/Emu48/EMU48.RC index 155416f..15e2e4b 100644 --- a/Sources/Emu48/EMU48.RC +++ b/Sources/Emu48/EMU48.RC @@ -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,5,0 - PRODUCTVERSION 1,6,5,0 + FILEVERSION 1,6,6,0 + PRODUCTVERSION 1,6,6,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 Emulator\0" - VALUE "FileVersion", "1, 6, 5, 0\0" + VALUE "FileVersion", "1, 6, 6, 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, 5, 0\0" + VALUE "ProductVersion", "1, 6, 6, 0\0" END END BLOCK "VarFileInfo" diff --git a/Sources/Emu48/Emu48.vcxproj b/Sources/Emu48/Emu48.vcxproj index b277133..bd73f8e 100644 --- a/Sources/Emu48/Emu48.vcxproj +++ b/Sources/Emu48/Emu48.vcxproj @@ -285,16 +285,16 @@ - LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;%(PreprocessorDefinitions) + LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;LODEPNG_NO_COMPILE_CRC;%(PreprocessorDefinitions) - LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;%(PreprocessorDefinitions) + LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;LODEPNG_NO_COMPILE_CRC;%(PreprocessorDefinitions) - LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;%(PreprocessorDefinitions) + LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;LODEPNG_NO_COMPILE_CRC;%(PreprocessorDefinitions) - LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;%(PreprocessorDefinitions) + LODEPNG_NO_COMPILE_ENCODER;LODEPNG_NO_COMPILE_DISK;LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS;LODEPNG_NO_COMPILE_ERROR_TEXT;LODEPNG_NO_COMPILE_CPP;LODEPNG_NO_COMPILE_CRC;%(PreprocessorDefinitions) @@ -312,7 +312,9 @@ Create pch.h + + diff --git a/Sources/Emu48/Emu48.vcxproj.filters b/Sources/Emu48/Emu48.vcxproj.filters index 0d598ae..ad42e68 100644 --- a/Sources/Emu48/Emu48.vcxproj.filters +++ b/Sources/Emu48/Emu48.vcxproj.filters @@ -78,9 +78,15 @@ Source Files + + Source Files + Source Files + + Source Files + Source Files diff --git a/Sources/Emu48/FILES.C b/Sources/Emu48/FILES.C index bee26d6..1666492 100644 --- a/Sources/Emu48/FILES.C +++ b/Sources/Emu48/FILES.C @@ -41,6 +41,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; @@ -54,15 +55,19 @@ BOOL bBackup = FALSE; static HANDLE hRomFile = 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; @@ -100,11 +105,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 @@ -207,7 +212,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 @@ -287,7 +292,7 @@ typedef struct tnode static TREENODE *nodePatch = NULL; -static BOOL PatchNibble(DWORD dwAddress, BYTE byPatch) +BOOL PatchNibble(DWORD dwAddress, BYTE byPatch) { PTREENODE p; @@ -444,6 +449,7 @@ BOOL PatchRom(LPCTSTR szFilename) { // patch ROM and save original nibble PatchNibble(dwAddress, Asc2Nib(lpBuf[nPos])); + bRomCrcCorrection = TRUE; } ++dwAddress; } @@ -478,7 +484,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; @@ -499,6 +505,7 @@ BOOL MapRom(LPCTSTR szFilename) { return FALSE; } + bRomCrcCorrection = FALSE; // ROM CRC correction disabled SetCurrentDirectory(szEmuDirectory); if (bRomRW) // ROM writeable { @@ -595,12 +602,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; @@ -636,19 +644,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; } } @@ -668,6 +676,7 @@ VOID UnmapRom(VOID) pbyRom = NULL; dwRomSize = 0; wRomCrc = 0; + bRomCrcCorrection = FALSE; // ROM CRC correction disabled return; } @@ -679,25 +688,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; } @@ -834,7 +842,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(); @@ -913,17 +921,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 @@ -952,10 +960,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) @@ -975,38 +982,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 @@ -1045,8 +1033,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 @@ -1081,9 +1068,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; @@ -1222,9 +1207,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; } @@ -1298,6 +1284,8 @@ BOOL SaveBackup(VOID) { WINDOWPLACEMENT wndpl; + BOOL bSucc = TRUE; + if (!bDocumentAvail) return FALSE; _ASSERT(nState != SM_RUN); // emulation engine is running @@ -1318,27 +1306,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? @@ -1365,17 +1367,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 @@ -1391,8 +1405,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) @@ -2601,7 +2619,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; @@ -2613,6 +2630,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; @@ -2624,7 +2643,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 @@ -2643,7 +2665,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); @@ -2688,18 +2714,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) @@ -2756,9 +2784,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; @@ -2773,10 +2811,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 } diff --git a/Sources/Emu48/KML.C b/Sources/Emu48/KML.C index 6513a20..80b5d1a 100644 --- a/Sources/Emu48/KML.C +++ b/Sources/Emu48/KML.C @@ -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.")); diff --git a/Sources/Emu48/LODEPNG.C b/Sources/Emu48/LODEPNG.C index 9d82e29..2c807ef 100644 --- a/Sources/Emu48/LODEPNG.C +++ b/Sources/Emu48/LODEPNG.C @@ -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; diff --git a/Sources/Emu48/LODEPNG.H b/Sources/Emu48/LODEPNG.H index fdafc77..81d4985 100644 --- a/Sources/Emu48/LODEPNG.H +++ b/Sources/Emu48/LODEPNG.H @@ -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 diff --git a/Sources/Emu48/MOPS.C b/Sources/Emu48/MOPS.C index ff6e96e..99409c8 100644 --- a/Sources/Emu48/MOPS.C +++ b/Sources/Emu48/MOPS.C @@ -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 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) { diff --git a/Sources/Emu48/PCH.H b/Sources/Emu48/PCH.H index a905b1c..555374a 100644 --- a/Sources/Emu48/PCH.H +++ b/Sources/Emu48/PCH.H @@ -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:\" \ diff --git a/Sources/Emu48/PNGCRC.C b/Sources/Emu48/PNGCRC.C new file mode 100644 index 0000000..d8493c5 --- /dev/null +++ b/Sources/Emu48/PNGCRC.C @@ -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; +} diff --git a/Sources/Emu48/ROMCRC.C b/Sources/Emu48/ROMCRC.C new file mode 100644 index 0000000..392c0dd --- /dev/null +++ b/Sources/Emu48/ROMCRC.C @@ -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; +} diff --git a/Sources/Emu48/SERIAL.C b/Sources/Emu48/SERIAL.C index c5b7a5b..52efb58 100644 --- a/Sources/Emu48/SERIAL.C +++ b/Sources/Emu48/SERIAL.C @@ -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 @@ -350,12 +353,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 diff --git a/Sources/Emu48/UDP.C b/Sources/Emu48/UDP.C index e404943..7e20930 100644 --- a/Sources/Emu48/UDP.C +++ b/Sources/Emu48/UDP.C @@ -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; diff --git a/Sources/GCCPatch/EMU48GCC.RC b/Sources/GCCPatch/EMU48GCC.RC index c10be25..8f5933f 100644 --- a/Sources/GCCPatch/EMU48GCC.RC +++ b/Sources/GCCPatch/EMU48GCC.RC @@ -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 | @@ -752,8 +752,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,6,5,0 - PRODUCTVERSION 1,6,5,0 + FILEVERSION 1,6,6,0 + PRODUCTVERSION 1,6,6,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -770,12 +770,12 @@ BEGIN BEGIN VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" - VALUE "FileVersion", "1, 6, 5, 0\0" + VALUE "FileVersion", "1, 6, 6, 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, 5, 0\0" + VALUE "ProductVersion", "1, 6, 6, 0\0" END END BLOCK "VarFileInfo" diff --git a/Sources/GCCPatch/Makefile b/Sources/GCCPatch/Makefile index 0afa653..2904cff 100644 --- a/Sources/GCCPatch/Makefile +++ b/Sources/GCCPatch/Makefile @@ -15,7 +15,8 @@ LODEPNGDEFINES= -DLODEPNG_NO_COMPILE_ENCODER \ -DLODEPNG_NO_COMPILE_DISK \ -DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS \ -DLODEPNG_NO_COMPILE_ERROR_TEXT \ - -DLODEPNG_NO_COMPILE_CPP + -DLODEPNG_NO_COMPILE_CPP \ + -DLODEPNG_NO_COMPILE_CRC LDFLAGS= -s -mwindows @@ -31,8 +32,8 @@ RSRCOBJ=$(PRJ).o OBJS=cursor.o ddeserv.o debugger.o disasm.o dismem.o display.o disrpl.o \ emu48.o engine.o fetch.o files.o i28f160.o keyboard.o \ keymacro.o kml.o lodepng.o lowbat.o mru.o mops.o opcodes.o \ - redeye.o rpl.o serial.o settings.o sndenum.o sound.o stack.o \ - symbfile.o timer.o udp.o \ + pngcrc.o redeye.o romcrc.o rpl.o serial.o settings.o sndenum.o \ + sound.o stack.o symbfile.o timer.o udp.o \ $(RSRCOBJ) LIBS=-lwinmm -lcomctl32 -lws2_32 -luuid @@ -122,9 +123,16 @@ opcodes.o: opcodes.c pch.h emu48.h types.h opcodes.h \ # pch.o: pch.c pch.h # $(CC) $(CFLAGS) $(DEFINES) -c -o pch.o pch.c +pngcrc.o: pngcrc.c pch.h + $(CC) $(CFLAGS) $(DEFINES) -c -o pngcrc.o pngcrc.c + redeye.o: redeye.c pch.h emu48.h types.h io.h $(CC) $(CFLAGS) $(DEFINES) -c -o redeye.o redeye.c +romcrc.o: romcrc.c pch.h emu48.h ops.h + $(CC) $(CFLAGS) $(DEFINES) -c -o romcrc.o romcrc.c + + rpl.o: rpl.c pch.h emu48.h types.h ops.h io.h $(CC) $(CFLAGS) $(DEFINES) -c -o rpl.o rpl.c diff --git a/Sources/GCCPatch/PCH.H b/Sources/GCCPatch/PCH.H index 7bc6e95..10a2d1f 100644 --- a/Sources/GCCPatch/PCH.H +++ b/Sources/GCCPatch/PCH.H @@ -45,3 +45,19 @@ #define VERIFY(f) ((VOID)(f)) #endif // _DEBUG #endif // VERIFY + +#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 + +enum { ProcessPowerThrottling = 4 }; + +typedef struct _PROCESS_POWER_THROTTLING_STATE { + ULONG Version; + ULONG ControlMask; + ULONG StateMask; +} PROCESS_POWER_THROTTLING_STATE, * PPROCESS_POWER_THROTTLING_STATE; diff --git a/Sources/GCCPatch/README.TXT b/Sources/GCCPatch/README.TXT index 88a235b..c9a1c94 100644 --- a/Sources/GCCPatch/README.TXT +++ b/Sources/GCCPatch/README.TXT @@ -67,4 +67,4 @@ Many thanks to Pedro A. Arranda Guti compatible. -07/19/22 (c) by Christoph Gießelink +04/18/23 (c) by Christoph Gießelink diff --git a/uninst.exe b/uninst.exe index 0d136b7..6bebbff 100755 Binary files a/uninst.exe and b/uninst.exe differ