Updated source code with Emu48 version 1.65+.

This commit is contained in:
dgis 2023-06-25 09:16:07 +02:00
parent 547d20aed3
commit ce269d7a43
60 changed files with 1372 additions and 403 deletions

View file

@ -58,8 +58,9 @@ LINKS
CHANGES CHANGES
Version 2.7 (2022-09-XX) Version 2.7 (2023-07-XX)
- Updated source code with Emu48 version 1.65+. This new version improve the serial communication.
- Attempt to fix haptic feedback with Android 13 (API deprecation). - Attempt to fix haptic feedback with Android 13 (API deprecation).
- Patch the ROM files to prevent the calculator to sleep for HP38G, HP39G, HP40G, HP48SX and HP48GX. - Patch the ROM files to prevent the calculator to sleep for HP38G, HP39G, HP40G, HP48SX and HP48GX.
There is an issue with this patch and the Flashcard for the HP49/50 because an already existing Flashcard embed the non patched ROM file, There is an issue with this patch and the Flashcard for the HP49/50 because an already existing Flashcard embed the non patched ROM file,

View file

@ -21,6 +21,14 @@ cmake_minimum_required(VERSION 3.4.1)
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE) #add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
# For the library LodePNG
add_compile_options(-DLODEPNG_NO_COMPILE_ENCODER)
add_compile_options(-DLODEPNG_NO_COMPILE_DISK)
add_compile_options(-DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS)
add_compile_options(-DLODEPNG_NO_COMPILE_ERROR_TEXT)
add_compile_options(-DLODEPNG_NO_COMPILE_CPP)
# add_compile_options(-DLODEPNG_NO_COMPILE_CRC) # Disabled to use new CRC function from lodepng.
add_compile_options(-DEMUXX=48) add_compile_options(-DEMUXX=48)
if(CMAKE_BUILD_TYPE STREQUAL Release) if(CMAKE_BUILD_TYPE STREQUAL Release)
@ -53,7 +61,7 @@ add_library( # Sets the name of the library.
src/main/cpp/core/disrpl.c src/main/cpp/core/disrpl.c
# src/main/cpp/core/Emu48.c #-> To rewrite # src/main/cpp/core/Emu48.c #-> To rewrite
src/main/cpp/core/engine.c src/main/cpp/core/engine.c
# src/main/cpp/core/external.c # Removed in Emu48+ for Windows version 1.62+ src/main/cpp/core/external.c
src/main/cpp/core/fetch.c src/main/cpp/core/fetch.c
src/main/cpp/core/files.c src/main/cpp/core/files.c
src/main/cpp/core/i28f160.c src/main/cpp/core/i28f160.c
@ -66,7 +74,9 @@ add_library( # Sets the name of the library.
src/main/cpp/core/mru.c src/main/cpp/core/mru.c
src/main/cpp/core/opcodes.c src/main/cpp/core/opcodes.c
src/main/cpp/core/pch.c src/main/cpp/core/pch.c
# src/main/cpp/core/pngcrc.c # Disabled to use new CRC function from lodepng.
src/main/cpp/core/redeye.c src/main/cpp/core/redeye.c
src/main/cpp/core/romcrc.c
src/main/cpp/core/rpl.c src/main/cpp/core/rpl.c
src/main/cpp/core/serial.c src/main/cpp/core/serial.c
src/main/cpp/core/settings.c src/main/cpp/core/settings.c
@ -77,6 +87,7 @@ add_library( # Sets the name of the library.
src/main/cpp/core/timer.c src/main/cpp/core/timer.c
# src/main/cpp/core/udp.c # src/main/cpp/core/udp.c
src/main/cpp/win32-layer.c src/main/cpp/win32-layer.c
src/main/cpp/android-layer.c src/main/cpp/android-layer.c
src/main/cpp/android-emu.c # Emu48.c rewrite src/main/cpp/android-emu.c # Emu48.c rewrite

View file

@ -58,6 +58,15 @@ LINKS
CHANGES CHANGES
Version 2.7 (2023-07-XX)
- Updated source code with Emu48 version 1.65+. This new version improve the serial communication.
- Attempt to fix haptic feedback with Android 13 (API deprecation).
- Patch the ROM files to prevent the calculator to sleep for HP38G, HP39G, HP40G, HP48SX and HP48GX.
There is an issue with this patch and the Flashcard for the HP49/50 because an already existing Flashcard embed the non patched ROM file,
and the CRC check failed and make a CPU reset!
- Fix a potential crash about the permission to access the files.
Version 2.6 (2022-08-19) Version 2.6 (2022-08-19)
- Updated source code from Eric Rechlin's Emu48 version 1.64+ that was merged from Christoph Gießelink's Emu48 version 1.65. This new version improve the serial communication. - Updated source code from Eric Rechlin's Emu48 version 1.64+ that was merged from Christoph Gießelink's Emu48 version 1.65. This new version improve the serial communication.

View file

@ -21,7 +21,7 @@ Global
Author "Casey Patterson && Sebastien Carlier" Author "Casey Patterson && Sebastien Carlier"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "cp_48g3.bmp" Bitmap "cp_48g3.bmp"
Debug 0 Debug 0
End End

View file

@ -13,7 +13,7 @@ Global
Author "Casey Patterson" Author "Casey Patterson"
Model "S" Model "S"
Rom "rom.48s" Rom "rom.48s"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "cp_48s3.bmp" Bitmap "cp_48s3.bmp"
Debug 0 Debug 0
End End

View file

@ -9,7 +9,7 @@ Global
Author "Christoph Giesselink" Author "Christoph Giesselink"
Model "A" Model "A"
Rom "rom.38g" Rom "rom.38g"
Patch "PATCHES.38G" Patch "patch.38g"
Debug 0 Debug 0
Bitmap "DEFAUL38.BMP" Bitmap "DEFAUL38.BMP"
End End

View file

@ -3,7 +3,7 @@ Global
Author "Sebastien Carlier" Author "Sebastien Carlier"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Debug 0 Debug 0
Bitmap "DEFAULTG.BMP" Bitmap "DEFAULTG.BMP"
End End

View file

@ -3,7 +3,7 @@ Global
Author "Sebastien Carlier" Author "Sebastien Carlier"
Model "S" Model "S"
Rom "rom.48s" Rom "rom.48s"
Patch "PATCHES.48" Patch "patch.48"
Debug 0 Debug 0
Bitmap "DEFAULTS.BMP" Bitmap "DEFAULTS.BMP"
End End

View file

@ -13,7 +13,7 @@ Global
Author "Casey Patterson" Author "Casey Patterson"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Debug 0 Debug 0
Bitmap "float_gx.bmp" Bitmap "float_gx.bmp"
End End

View file

@ -3,7 +3,7 @@ Global
Author "Jeffery L. McMahan" Author "Jeffery L. McMahan"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "jemac.bmp" Bitmap "jemac.bmp"
Debug 0 Debug 0
End End

View file

@ -10,7 +10,7 @@ Global
Hardware "Yorke" Hardware "Yorke"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "Wombat3 48GX.bmp" Bitmap "Wombat3 48GX.bmp"
Debug 0 Debug 0
End End

View file

@ -10,7 +10,7 @@ Global
Hardware "Yorke" Hardware "Yorke"
Model "S" Model "S"
Rom "rom.48s" Rom "rom.48s"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "Wombat3 48SX.bmp" Bitmap "Wombat3 48SX.bmp"
Debug 0 Debug 0
End End

View file

@ -11,7 +11,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "PATCHES.49G" Patch "patch.49g"
Bitmap "calypso2k.png" Bitmap "calypso2k.png"
Color 0 0 0 0 Color 0 0 0 0
#Scale 3 9 #Scale 3 9

View file

@ -11,7 +11,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "PATCHES.49G" Patch "patch.49g"
Bitmap "calypso4k.png" Bitmap "calypso4k.png"
Color 0 0 0 0 Color 0 0 0 0
#Scale 3 18 #Scale 3 18

View file

@ -15,7 +15,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "6" # 6 for 64K RAM, A for 32K RAM Model "6" # 6 for 64K RAM, A for 32K RAM
Rom "rom.38g" Rom "rom.38g"
Patch "PATCHES.38G" Patch "patch.38g"
Bitmap "real38g-l.png" Bitmap "real38g-l.png"
Icon "38g.ico" Icon "38g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -15,7 +15,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "6" # 6 for 64K RAM, A for 32K RAM Model "6" # 6 for 64K RAM, A for 32K RAM
Rom "rom.38g" Rom "rom.38g"
Patch "PATCHES.38G" Patch "patch.38g"
Bitmap "real38g-lc.png" Bitmap "real38g-lc.png"
Icon "38g.ico" Icon "38g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39g-l.png" Bitmap "real39g-l.png"
Icon "39g.ico" Icon "39g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39g-lc.png" Bitmap "real39g-lc.png"
Icon "39g.ico" Icon "39g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39gp-l.png" Bitmap "real39gp-l.png"
Icon "39gp.ico" Icon "39gp.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39gp-lc.png" Bitmap "real39gp-lc.png"
Icon "39gp.ico" Icon "39gp.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39gs-l.png" Bitmap "real39gs-l.png"
Icon "39gs.ico" Icon "39gs.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 39 Class 39
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39gs-lc.png" Bitmap "real39gs-lc.png"
Icon "39gs.ico" Icon "39gs.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 40 Class 40
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real40g-l.png" Bitmap "real40g-l.png"
Icon "39g.ico" Icon "39g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 40 Class 40
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real39g-lc.png" Bitmap "real39g-lc.png"
Icon "40g.ico" Icon "40g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 40 Class 40
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real40gs-l.png" Bitmap "real40gs-l.png"
Icon "40gs.ico" Icon "40gs.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Model "E" Model "E"
Class 40 Class 40
Rom "rom.39g" Rom "rom.39g"
Patch "PATCHES.39G" Patch "patch.39g"
Bitmap "real40gs-lc.png" Bitmap "real40gs-lc.png"
Icon "40gs.ico" Icon "40gs.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "2" Model "2"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real48gii-l.png" Bitmap "real48gii-l.png"
Icon "48gii.ico" Icon "48gii.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "2" Model "2"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real48gii-lc.png" Bitmap "real48gii-lc.png"
Icon "48gii.ico" Icon "48gii.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "real48gx-l.png" Bitmap "real48gx-l.png"
Icon "48gx.ico" Icon "48gx.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "G" Model "G"
Rom "rom.48g" Rom "rom.48g"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "real48gx-lc.png" Bitmap "real48gx-lc.png"
Icon "48gx.ico" Icon "48gx.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "S" Model "S"
Rom "rom.48s" Rom "rom.48s"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "real48sx-l.png" Bitmap "real48sx-l.png"
Icon "48sx.ico" Icon "48sx.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,7 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "S" Model "S"
Rom "rom.48s" Rom "rom.48s"
Patch "PATCHES.48" Patch "patch.48"
Bitmap "real48sx-lc.png" Bitmap "real48sx-lc.png"
Icon "48sx.ico" Icon "48sx.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "X" Model "X"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real49g-l.png" Bitmap "real49g-l.png"
Icon "49g.ico" Icon "49g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "X" Model "X"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real49g-lc.png" Bitmap "real49g-lc.png"
Icon "49g.ico" Icon "49g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "Q" Model "Q"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real49gp-l.png" Bitmap "real49gp-l.png"
Icon "49gp.ico" Icon "49gp.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Author "Eric Rechlin" Author "Eric Rechlin"
Model "Q" Model "Q"
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real49gp-lc.png" Bitmap "real49gp-lc.png"
Icon "49gp.ico" Icon "49gp.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real50g-blue-l.png" Bitmap "real50g-blue-l.png"
Icon "50g.ico" Icon "50g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -14,6 +14,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real50g-blue-lc.png" Bitmap "real50g-blue-lc.png"
Icon "50g.ico" Icon "50g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -15,6 +15,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real50g-l.png" Bitmap "real50g-l.png"
Icon "50g.ico" Icon "50g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -15,6 +15,7 @@ Global
Model "Q" Model "Q"
Class 50 Class 50
Rom "rom.49g" Rom "rom.49g"
Patch "patch.49g"
Bitmap "real50g-lc.png" Bitmap "real50g-lc.png"
Icon "50g.ico" Icon "50g.ico"
Color 0 190 190 190 Color 0 190 190 190

View file

@ -13,7 +13,7 @@
#include "kml.h" #include "kml.h"
#include "debugger.h" #include "debugger.h"
#define VERSION "1.64+" #define VERSION "1.65+"
#ifdef _DEBUG #ifdef _DEBUG
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug"); LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
@ -2042,19 +2042,19 @@ LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lPar
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{ {
typedef DWORD (WINAPI *LPFN_STIP)(HANDLE hThread,DWORD dwIdealProcessor);
MSG msg; MSG msg;
WNDCLASS wc; WNDCLASS wc;
ATOM classAtom; ATOM classAtom;
RECT rectWindow; RECT rectWindow;
HACCEL hAccel; HACCEL hAccel;
DWORD dwThreadId; DWORD dwThreadId;
LPFN_STIP fnSetThreadIdealProcessor;
DWORD dwProcessor; DWORD dwProcessor;
HSZ hszService, hszTopic; // variables for DDE server HSZ hszService, hszTopic; // variables for DDE server
LPTSTR lpFilePart; LPTSTR lpFilePart;
// module handle to kernel32
const HMODULE hmKernel32 = GetModuleHandle(_T("kernel32"));
// enable memory leak detection // enable memory leak detection
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
@ -2147,6 +2147,26 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
return 0; // quit program 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 // Create window
rectWindow.left = 0; rectWindow.left = 0;
rectWindow.top = 0; rectWindow.top = 0;
@ -2197,15 +2217,29 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
return FALSE; return FALSE;
} }
// SetThreadIdealProcessor() is available since Windows NT4.0 // get processor for Saturn CPU thread
fnSetThreadIdealProcessor = (LPFN_STIP) GetProcAddress(GetModuleHandle(_T("kernel32")), {
"SetThreadIdealProcessor"); // 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 if (fnGetCurrentProcessorNumber != NULL) // running on Vista or later
dwProcessor = (fnSetThreadIdealProcessor != NULL) // running on NT4.0 or later {
? fnSetThreadIdealProcessor(hThread,MAXIMUM_PROCESSORS) // get ideal processor no. dwProcessor = fnGetCurrentProcessorNumber(); // get current processor number
: 0; // select 1st processor }
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() // on multiprocessor machines for QueryPerformanceCounter()
VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor))); VERIFY(SetThreadAffinityMask(hThread,(DWORD_PTR) (1 << dwProcessor)));
ResumeThread(hThread); // start thread ResumeThread(hThread); // start thread

View file

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

View file

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

View file

@ -29,31 +29,36 @@ typedef struct
static VOID PutSn(String *str, LPCTSTR szVal, DWORD dwLen) 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 LPTSTR szNewBuffer;
VERIFY(str->szBuffer = (LPTSTR) malloc(str->dwSize * sizeof(TCHAR)));
str->dwPos = 0; 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 (str->szBuffer)
if (dwLen > 0) // actual string length
{ {
// 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)); CopyMemory(&str->szBuffer[str->dwPos],szVal,dwLen * sizeof(TCHAR));
str->dwPos += dwLen; 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) static BOOL BINx(DWORD *pdwAddr,INT nBinLen,String *str)
{ {
LPBYTE pbyNumber; LPBYTE pbyNumber = (LPBYTE) malloc(nBinLen);
INT i; if (pbyNumber != NULL)
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
{ {
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; return FALSE;
} }
@ -327,29 +333,31 @@ static BOOL DoIntStream(DWORD *pdwAddr,String *str,UINT *pnLevel)
dwLength -= 5; // object length dwLength -= 5; // object length
VERIFY(pbyData = (LPBYTE) malloc(dwLength)); pbyData = (LPBYTE) malloc(dwLength);
if (pbyData != NULL)
for (i = 0; i < dwLength; ++i) // read data
pbyData[i] = RplReadNibble(pdwAddr);
if (dwLength <= 1) // special implementation for zero
{ {
_ASSERT(dwLength == 0 || (dwLength == 1 && pbyData[0] == 0)); for (i = 0; i < dwLength; ++i) // read data
PutC(str,_T('0')); pbyData[i] = RplReadNibble(pdwAddr);
}
else
{
if (pbyData[--dwLength] == 9) // negative number
PutC(str,_T('-'));
while (dwLength > 0) // write rest of zint if (dwLength <= 1) // special implementation for zero
{ {
// use only decimal part for translation _ASSERT(dwLength == 0 || (dwLength == 1 && pbyData[0] == 0));
PutC(str,cHex[pbyData[--dwLength]]); 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; return FALSE;
UNREFERENCED_PARAMETER(pnLevel); UNREFERENCED_PARAMETER(pnLevel);
} }
@ -1291,9 +1299,9 @@ DWORD RplSkipObject(DWORD dwAddr)
LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr) LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr)
{ {
String str = { 0 }; String str = { 0, NULL, 0 };
DWORD dwNxtAddr; DWORD dwNxtAddr;
UINT nLevel = 0; // don't nest DOCOL objects UINT nLevel = 0; // don't nest DOCOL objects
dwNxtAddr = dwAddr; // init next address dwNxtAddr = dwAddr; // init next address
@ -1302,7 +1310,7 @@ LPTSTR RplDecodeObject(DWORD dwAddr, DWORD *pdwNxtAddr)
PutC(&str,0); // set EOS 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]))); VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0])));
// return address of next object // 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) LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
{ {
String str = { 0 }; String str = { 0, NULL, 0 };
LPCTSTR lpszName; LPCTSTR lpszName;
LPTSTR lpszObject; LPTSTR lpszObject;
DWORD dwLevel,dwAddr,dwNxtAddr; DWORD dwLevel,dwAddr,dwNxtAddr;
@ -1486,6 +1494,10 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
for (dwAddr = dwStartAddr;dwAddr < dwEndAddr; dwAddr = dwNxtAddr) for (dwAddr = dwStartAddr;dwAddr < dwEndAddr; dwAddr = dwNxtAddr)
{ {
lpszObject = RplDecodeObject(dwAddr,&dwNxtAddr); lpszObject = RplDecodeObject(dwAddr,&dwNxtAddr);
if (lpszObject == NULL) // no memory
{
break; // break decoding
}
if (dwLevel > 0 && lstrcmp(lpszObject,_T(";")) == 0) if (dwLevel > 0 && lstrcmp(lpszObject,_T(";")) == 0)
--dwLevel; --dwLevel;
@ -1586,7 +1598,7 @@ LPTSTR RplCreateObjView(DWORD dwStartAddr, DWORD dwEndAddr, BOOL bSingleObj)
PutC(&str,0); // set EOS 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]))); VERIFY(str.szBuffer = (LPTSTR) realloc(str.szBuffer,str.dwPos * sizeof(str.szBuffer[0])));
return str.szBuffer; return str.szBuffer;
} }

View file

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

View file

@ -0,0 +1,101 @@
/*
* external.c
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
*
*/
#include "pch.h"
#include "Emu48.h"
#include "ops.h"
#define SAMPLES_PER_SEC 44100 // sound sampling rate
//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name
//#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56
// memory address for flags -53 to -56
// CdB for HP: add apples beep management
#define SFLAG53_56 ( (cCurrentRomType=='6') \
? 0xE0E4F \
: ( (cCurrentRomType=='A') \
? 0xF0E4F \
: ( (cCurrentRomType!='E' && cCurrentRomType!='X' && cCurrentRomType!='P' && cCurrentRomType!='2' && cCurrentRomType!='Q') \
? ( (cCurrentRomType=='S') \
? 0x706D2 \
: 0x80850 \
) \
: 0x80F0F \
) \
) \
)
VOID External(CHIPSET* w) // Beep patch
{
BYTE fbeep;
DWORD freq,dur;
freq = Npack(w->D,5); // frequency in Hz
dur = Npack(w->C,5); // duration in ms
Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56
w->carry = TRUE; // setting of no beep
if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz
{
if (freq > 4400) freq = 4400; // high limit of HP (SX)
SoundBeep(freq,dur); // beeping
// estimate cpu cycles for beeping time (2MHz / 4MHz)
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);
// original routine return with...
w->P = 0; // P=0
w->intk = TRUE; // INTON
w->carry = FALSE; // RTNCC
}
w->pc = rstkpop();
return;
}
VOID RCKBp(CHIPSET* w) // ROM Check Beep patch
{
DWORD dw2F,dwCpuFreq;
DWORD freq,dur;
BYTE f,d;
f = w->C[1]; // f = freq ctl
d = w->C[0]; // d = duration ctl
if (cCurrentRomType == 'S') // Clarke chip with 48S ROM
{
// CPU strobe frequency @ RATE 14 = 1.97MHz
dwCpuFreq = ((14 + 1) * 524288) >> 2;
dw2F = f * 126 + 262; // F=f*63+131
}
else // York chip with 48G and later ROM
{
// CPU strobe frequency @ RATE 27 = 3.67MHz
// CPU strobe frequency @ RATE 29 = 3.93MHz
dwCpuFreq = ((27 + 1) * 524288) >> 2;
dw2F = f * 180 + 367; // F=f*90+183.5
}
freq = dwCpuFreq / dw2F;
dur = (dw2F * (256 - 16 * d)) * 1000 / 2 / dwCpuFreq;
if (freq > 4400) freq = 4400; // high limit of HP
SoundBeep(freq,dur); // beeping
// estimate cpu cycles for beeping time (2MHz / 4MHz)
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);
w->P = 0; // P=0
w->carry = FALSE; // RTNCC
w->pc = rstkpop();
return;
}

View file

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

View file

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

View file

@ -1,7 +1,7 @@
/* /*
LodePNG version 20220717 LodePNG version 20230410
Copyright (c) 2005-2022 Lode Vandevenne Copyright (c) 2005-2023 Lode Vandevenne
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages 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*/ #pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
#endif /*_MSC_VER */ #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 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_MAX(a, b) (((a) > (b)) ? (a) : (b))
#define LODEPNG_MIN(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) #if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_DECODER)
/* Safely check if adding two integers will overflow (no undefined /* 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 #ifdef LODEPNG_COMPILE_CRC
/* CRC polynomial: 0xedb88320 */
static unsigned lodepng_crc32_table[256] = { static const unsigned lodepng_crc32_table0[256] = {
0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, 0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u,
249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, 0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,
498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u,
325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, 0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u,
997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, 0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u,
651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, 0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu,
671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du,
1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, 0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, 0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u,
1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, 0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u,
1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu,
1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, 0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u,
1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, 0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, 0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu,
3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, 0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u,
3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, 0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u,
4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, 0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, 0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu,
3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, 0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u,
3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, 0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du,
2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, 0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u,
2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, 0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, 0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, 0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u 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) { unsigned lodepng_crc32(const unsigned char* data, size_t length) {
/*Using the Slicing by Eight algorithm*/
unsigned r = 0xffffffffu; unsigned r = 0xffffffffu;
size_t i; while(length >= 8) {
for(i = 0; i < length; ++i) { r = lodepng_crc32_table7[(data[0] ^ (r & 0xffu))] ^
r = lodepng_crc32_table[(r ^ data[i]) & 0xffu] ^ (r >> 8u); 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; return r ^ 0xffffffffu;
} }
#else /* LODEPNG_COMPILE_CRC */ #else /* LODEPNG_COMPILE_CRC */
/*in this case, the function is only declared here, and must be defined externally /*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); unsigned lodepng_crc32(const unsigned char* data, size_t length);
#endif /* LODEPNG_COMPILE_CRC */ #endif /* LODEPNG_COMPILE_CRC */
@ -3964,15 +4237,14 @@ static unsigned auto_choose_color(LodePNGColorMode* mode_out,
#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ #endif /* #ifdef LODEPNG_COMPILE_ENCODER */
/* /*Paeth predictor, used by PNG filter type 4*/
Paeth predictor, used by PNG filter type 4 static unsigned char paethPredictor(unsigned char a, unsigned char b, unsigned char c) {
The parameters are of type short, but should come from unsigned chars, the shorts /* the subtractions of unsigned char cast it to a signed type.
are only needed to make the paeth calculation correct. 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);
static unsigned char paethPredictor(short a, short b, short c) { short pb = (a - c) < 0 ? -(a - c) : (a - c);
short pa = LODEPNG_ABS(b - c); /* writing it out like this compiles to something faster than introducing a temp variable*/
short pb = LODEPNG_ABS(a - c); short pc = (a + b - c - c) < 0 ? -(a + b - c - c) : (a + b - c - c);
short pc = LODEPNG_ABS(a + b - c - c);
/* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */ /* return input value associated with smallest of pa, pb, pc (with certain priority if equal) */
if(pb < pa) { a = b; pa = pb; } if(pb < pa) { a = b; pa = pb; }
return (pc < pa) ? c : a; return (pc < pa) ? c : a;
@ -4168,47 +4440,108 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
break; break;
case 4: case 4:
if(precon) { if(precon) {
size_t j = 0; /* Unroll independent paths of this predictor. Whether this speeds up
for(i = 0; i != bytewidth; ++i) { anything depends on compiler and settings. */
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ 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;
/* Unroll independent paths of the paeth predictor. A 6x and 8x version is also possible but that unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0;
adds too much code. Whether this speeds up anything depends on compiler and settings. */ unsigned char a6, b6 = 0, c6, d6 = 0, a7, b7 = 0, c7, d7 = 0;
if(bytewidth >= 4) { for(i = 0; i + 7 < length; i += 8) {
for(; i + 3 < length; i += 4, j += 4) { c0 = b0; c1 = b1; c2 = b2; c3 = b3;
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3]; c4 = b4; c5 = b5; c6 = b6; c7 = b7;
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3]; b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3];
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3]; b4 = precon[i + 4]; b5 = precon[i + 5]; b6 = precon[i + 6]; b7 = precon[i + 7];
unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2], q3 = precon[j + 3]; a0 = d0; a1 = d1; a2 = d2; a3 = d3;
recon[i + 0] = s0 + paethPredictor(r0, p0, q0); a4 = d4; a5 = d5; a6 = d6; a7 = d7;
recon[i + 1] = s1 + paethPredictor(r1, p1, q1); d0 = scanline[i + 0] + paethPredictor(a0, b0, c0);
recon[i + 2] = s2 + paethPredictor(r2, p2, q2); d1 = scanline[i + 1] + paethPredictor(a1, b1, c1);
recon[i + 3] = s3 + paethPredictor(r3, p3, q3); 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) { } else if(bytewidth == 6) {
for(; i + 2 < length; i += 3, j += 3) { unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0;
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2]; unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0;
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2]; unsigned char a4, b4 = 0, c4, d4 = 0, a5, b5 = 0, c5, d5 = 0;
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2]; for(i = 0; i + 5 < length; i += 6) {
unsigned char q0 = precon[j + 0], q1 = precon[j + 1], q2 = precon[j + 2]; c0 = b0; c1 = b1; c2 = b2;
recon[i + 0] = s0 + paethPredictor(r0, p0, q0); c3 = b3; c4 = b4; c5 = b5;
recon[i + 1] = s1 + paethPredictor(r1, p1, q1); b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2];
recon[i + 2] = s2 + paethPredictor(r2, p2, q2); 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) { } else if(bytewidth == 4) {
for(; i + 1 < length; i += 2, j += 2) { unsigned char a0, b0 = 0, c0, d0 = 0, a1, b1 = 0, c1, d1 = 0;
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1]; unsigned char a2, b2 = 0, c2, d2 = 0, a3, b3 = 0, c3, d3 = 0;
unsigned char r0 = recon[j + 0], r1 = recon[j + 1]; for(i = 0; i + 3 < length; i += 4) {
unsigned char p0 = precon[i + 0], p1 = precon[i + 1]; c0 = b0; c1 = b1; c2 = b2; c3 = b3;
unsigned char q0 = precon[j + 0], q1 = precon[j + 1]; b0 = precon[i + 0]; b1 = precon[i + 1]; b2 = precon[i + 2]; b3 = precon[i + 3];
recon[i + 0] = s0 + paethPredictor(r0, p0, q0); a0 = d0; a1 = d1; a2 = d2; a3 = d3;
recon[i + 1] = s1 + paethPredictor(r1, p1, q1); 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]*/
} }
} }
/* finish any remaining bytes */
for(; i != length; ++i, ++j) { for(; i != length; ++i) {
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[j])); recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
} }
} else { } else {
size_t j = 0; size_t j = 0;

View file

@ -1,7 +1,7 @@
/* /*
LodePNG version 20220717 LodePNG version 20230410
Copyright (c) 2005-2022 Lode Vandevenne Copyright (c) 2005-2023 Lode Vandevenne
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages 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 #endif
/*Disable built-in CRC function, in that case a custom implementation of /*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 #ifndef LODEPNG_NO_COMPILE_CRC
/*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one, /*pass -DLODEPNG_NO_COMPILE_CRC to the compiler to disable the built-in one,
or comment out LODEPNG_COMPILE_CRC below*/ 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: Not all changes are listed here, the commit history in github lists more:
https://github.com/lvandeve/lodepng 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. *) 13 jun 2022: added support for the sBIT chunk.
*) 09 jan 2022: minor decoder speed improvements. *) 09 jan 2022: minor decoder speed improvements.
*) 27 jun 2021: added warnings that file reading/writing functions don't support *) 27 jun 2021: added warnings that file reading/writing functions don't support

View file

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

View file

@ -61,6 +61,24 @@ typedef ULONG ULONG_PTR, *PULONG_PTR;
typedef LONG LONG_PTR, *PLONG_PTR; typedef LONG LONG_PTR, *PLONG_PTR;
#endif #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 _MSC_VER >= 1400 // valid for VS2005 and later
#if defined _M_IX86 #if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\" \ #pragma comment(linker,"/manifestdependency:\" \

View file

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

View file

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

View file

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

View file

@ -10,27 +10,27 @@
#include "Emu48.h" #include "Emu48.h"
TCHAR szUdpServer[1024] = _T("localhost"); 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) 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; return;
} }
BOOL SendByteUdp(BYTE byData) BOOL SendByteUdp(BYTE byData)
{ {
WSADATA wsd; WSADATA wsd;
SOCKET sClient; SOCKET sClient;
SOCKADDR_IN sServer;
BOOL bErr = TRUE; BOOL bErr = TRUE;
VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0); 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; LPSTR lpszIpAddr;
@ -38,7 +38,7 @@ BOOL SendByteUdp(BYTE byData)
DWORD dwLength = lstrlen(szUdpServer) + 1; DWORD dwLength = lstrlen(szUdpServer) + 1;
if ((lpszIpAddr = (LPSTR) _alloca(dwLength)) == NULL) if ((lpszIpAddr = (LPSTR) _alloca(dwLength)) == NULL)
return TRUE; // server not found return TRUE; // server ip address not found
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
szUdpServer, dwLength, szUdpServer, dwLength,
@ -47,27 +47,26 @@ BOOL SendByteUdp(BYTE byData)
lpszIpAddr = szUdpServer; lpszIpAddr = szUdpServer;
#endif #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 // 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); PHOSTENT host = gethostbyname(lpszIpAddr);
if (host == NULL) 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 // create UDP socket
if ((sClient = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET) if ((sClient = socket(AF_INET, SOCK_DGRAM, 0)) != INVALID_SOCKET)
{ {
sServer.sin_family = AF_INET;
sServer.sin_port = htons(wUdpPort); sServer.sin_port = htons(wUdpPort);
sServer.sin_addr.s_addr = ip_addr.s_addr;
// transmit data byte // transmit data byte
bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR; bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR;