mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
Version 2.4 (2021-12-08)
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
This commit is contained in:
parent
1b26b74f48
commit
8a54fb0b33
14 changed files with 365 additions and 187 deletions
|
@ -58,6 +58,11 @@ LINKS
|
||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
|
Version 2.4 (2021-12-08)
|
||||||
|
|
||||||
|
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
||||||
|
|
||||||
|
|
||||||
Version 2.3 (2021-10-19)
|
Version 2.3 (2021-10-19)
|
||||||
|
|
||||||
- Add an experimental serial port support (via USB OTG).
|
- Add an experimental serial port support (via USB OTG).
|
||||||
|
@ -251,7 +256,7 @@ TODO
|
||||||
|
|
||||||
BUILD
|
BUILD
|
||||||
|
|
||||||
Emu48 for Android is built with Android Studio 4.1 (2020).
|
Emu48 for Android is built with Android Studio 2020.3.1 (2021).
|
||||||
And to generate an installable APK file with a real Android device, it MUST be signed.
|
And to generate an installable APK file with a real Android device, it MUST be signed.
|
||||||
|
|
||||||
Either use Android Studio:
|
Either use Android Studio:
|
||||||
|
|
|
@ -33,8 +33,8 @@ android {
|
||||||
applicationId "org.emulator.forty.eight"
|
applicationId "org.emulator.forty.eight"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 22
|
versionCode 23
|
||||||
versionName "2.3"
|
versionName "2.4"
|
||||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
|
|
|
@ -114,6 +114,21 @@ h3 { color:red; font-size:1.1em; }
|
||||||
into the native Emu48 ROM format is not necessary any more. You can
|
into the native Emu48 ROM format is not necessary any more. You can
|
||||||
still use the classic way extracting them from your own calculator.
|
still use the classic way extracting them from your own calculator.
|
||||||
</p>
|
</p>
|
||||||
|
<p>The command line <i>Convert</i> utility delivered with the Emu48
|
||||||
|
program package was originally designed to convert HP48 ROM images
|
||||||
|
files from one of the various used ROM image formats of the 90s to
|
||||||
|
the unpacked format originally used by Emu48. The 2nd important
|
||||||
|
task of this tool is updating the I/O register area with zeros.
|
||||||
|
Most images had been created with a ROM upload program where the
|
||||||
|
I/O register area was mapped over the ROM content and so the ROM
|
||||||
|
image file contain a wrong content at this position. Executing the
|
||||||
|
selftest on a HP38 or a HP48 will report an IROM fail then. To fix
|
||||||
|
this the <i>Convert</i> utility overwrites the I/O register area
|
||||||
|
in the destination file with zeros. Final notice, the convert
|
||||||
|
utility shows the CRC result after the file convert and a passed
|
||||||
|
ROM CRC test does <u><b>not</b></u> imply, that the source file
|
||||||
|
is in an Emu48 suitable format!
|
||||||
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>HP38
|
<li>HP38
|
||||||
<p>To upload the ROM of your HP38G, you will need a special aplet
|
<p>To upload the ROM of your HP38G, you will need a special aplet
|
||||||
|
@ -636,10 +651,7 @@ h3 { color:red; font-size:1.1em; }
|
||||||
Cyrille de Brebisson of Hewlett-Packard.</p>
|
Cyrille de Brebisson of Hewlett-Packard.</p>
|
||||||
<h1><a name=s15>15. License</a></h1>
|
<h1><a name=s15>15. License</a></h1>
|
||||||
<p>Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator<br>
|
<p>Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator<br>
|
||||||
Copyright (C) 2020 Christoph Gießelink</p>
|
Copyright (C) 2021 Christoph Gießelink</p>
|
||||||
<p>Emu48+ - A 39g+/39gs/40gs/48gII/49g+/50g Emulator<br>
|
|
||||||
Copyright (C) 2020 Cyrille de Brebisson<br>
|
|
||||||
Additional changes by Bill Graves and Eric Rechlin</p>
|
|
||||||
<p>This program is free software; you can redistribute it and/or modify it
|
<p>This program is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU General Public License as published by the Free
|
under the terms of the GNU General Public License as published by the Free
|
||||||
Software Foundation; either version 2 of the License, or (at your option)
|
Software Foundation; either version 2 of the License, or (at your option)
|
||||||
|
|
|
@ -58,6 +58,11 @@ LINKS
|
||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
|
Version 2.4 (2021-12-08)
|
||||||
|
|
||||||
|
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
||||||
|
|
||||||
|
|
||||||
Version 2.3 (2021-10-19)
|
Version 2.3 (2021-10-19)
|
||||||
|
|
||||||
- Add an experimental serial port support (via USB OTG).
|
- Add an experimental serial port support (via USB OTG).
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
#include "kml.h"
|
#include "kml.h"
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
|
|
||||||
#define VERSION "1.62+"
|
#define VERSION "1.63+"
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
|
LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
|
||||||
|
@ -1753,26 +1753,40 @@ static LRESULT OnAbout(VOID)
|
||||||
|
|
||||||
static VOID OnContextMenu(LPARAM lParam)
|
static VOID OnContextMenu(LPARAM lParam)
|
||||||
{
|
{
|
||||||
HMENU hMenu;
|
|
||||||
POINT pt,ptc;
|
|
||||||
|
|
||||||
if (GetMenu(hWnd) == NULL) // no main window menu
|
if (GetMenu(hWnd) == NULL) // no main window menu
|
||||||
{
|
{
|
||||||
|
BOOL bContextMenu = TRUE; // call context menu
|
||||||
|
POINT pt;
|
||||||
|
|
||||||
POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position
|
POINTSTOPOINT(pt,MAKEPOINTS(lParam)); // mouse position
|
||||||
|
|
||||||
if (pt.x == -1 && pt.y == -1) // VK_APPS
|
if (pt.x == -1 && pt.y == -1) // VK_APPS
|
||||||
{
|
{
|
||||||
pt.x = 15; // open context help at client position 15,15
|
RECT rc;
|
||||||
pt.y = 15;
|
|
||||||
VERIFY(ClientToScreen(hWnd,&pt));
|
GetCursorPos(&pt); // get current mouse position
|
||||||
|
GetWindowRect(hWnd,&rc); // get position of active window
|
||||||
|
if (PtInRect(&rc,pt)==FALSE) // mouse position outside active window
|
||||||
|
{
|
||||||
|
pt.x = 15; // open context help at client position 15,15
|
||||||
|
pt.y = 15;
|
||||||
|
VERIFY(ClientToScreen(hWnd,&pt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // got a mouse position
|
||||||
|
{
|
||||||
|
POINT ptc = pt;
|
||||||
|
// convert mouse into client position
|
||||||
|
VERIFY(ScreenToClient(hWnd,&ptc));
|
||||||
|
|
||||||
|
// in client area not over a button
|
||||||
|
bContextMenu = (ptc.y >= 0 && !MouseIsButton(ptc.x,ptc.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
ptc = pt;
|
if (bContextMenu) // call the context menu
|
||||||
VERIFY(ScreenToClient(hWnd,&ptc)); // convert mouse into client position
|
|
||||||
|
|
||||||
// in client area not over a button
|
|
||||||
if (ptc.y >= 0 && !MouseIsButton(ptc.x,ptc.y))
|
|
||||||
{
|
{
|
||||||
|
HMENU hMenu;
|
||||||
|
|
||||||
// load the popup menu resource
|
// load the popup menu resource
|
||||||
if ((hMenu = LoadMenu(hApp,MAKEINTRESOURCE(IDM_MENU))) != NULL)
|
if ((hMenu = LoadMenu(hApp,MAKEINTRESOURCE(IDM_MENU))) != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2901,8 +2901,6 @@ static INT_PTR CALLBACK EnterBreakpoint(HWND hDlg, UINT message, WPARAM wParam,
|
||||||
{
|
{
|
||||||
static BP_T *sBp;
|
static BP_T *sBp;
|
||||||
|
|
||||||
DWORD dwAddr;
|
|
||||||
|
|
||||||
switch (message)
|
switch (message)
|
||||||
{
|
{
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
|
@ -2921,9 +2919,8 @@ static INT_PTR CALLBACK EnterBreakpoint(HWND hDlg, UINT message, WPARAM wParam,
|
||||||
case IDC_BPREAD: sBp->nType = BP_READ; return TRUE;
|
case IDC_BPREAD: sBp->nType = BP_READ; return TRUE;
|
||||||
case IDC_BPWRITE: sBp->nType = BP_WRITE; return TRUE;
|
case IDC_BPWRITE: sBp->nType = BP_WRITE; return TRUE;
|
||||||
case IDOK:
|
case IDOK:
|
||||||
if (!GetAddr(hDlg,IDC_ENTERADR,&dwAddr,0xFFFFF,disassembler_symb))
|
if (!GetAddr(hDlg,IDC_ENTERADR,&sBp->dwAddr,0xFFFFF,disassembler_symb))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
sBp->dwAddr = dwAddr;
|
|
||||||
// no break
|
// no break
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
EndDialog(hDlg,wParam);
|
EndDialog(hDlg,wParam);
|
||||||
|
@ -2955,42 +2952,35 @@ static __inline BOOL OnDrawBreakWnd(LPDRAWITEMSTRUCT lpdis)
|
||||||
COLORREF crBkColor,crTextColor;
|
COLORREF crBkColor,crTextColor;
|
||||||
HDC hdcMem;
|
HDC hdcMem;
|
||||||
HBITMAP hBmpOld;
|
HBITMAP hBmpOld;
|
||||||
INT i;
|
|
||||||
|
|
||||||
if (lpdis->itemID == -1) // no item in list box
|
if (lpdis->itemID == -1) // no item in list box
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
crBkColor = GetBkColor(lpdis->hDC); // save actual color settings
|
||||||
|
crTextColor = GetTextColor(lpdis->hDC);
|
||||||
|
|
||||||
if (lpdis->itemState & ODS_SELECTED) // cursor line
|
if (lpdis->itemState & ODS_SELECTED) // cursor line
|
||||||
{
|
{
|
||||||
crBkColor = COLOR_NAVY;
|
SetBkColor(lpdis->hDC,GetSysColor(COLOR_HIGHLIGHT));
|
||||||
crTextColor = COLOR_WHITE;
|
SetTextColor(lpdis->hDC,GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
crBkColor = COLOR_WHITE;
|
|
||||||
crTextColor = COLOR_BLACK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write Text
|
// write Text
|
||||||
crBkColor = SetBkColor(lpdis->hDC,crBkColor);
|
|
||||||
crTextColor = SetTextColor(lpdis->hDC,crTextColor);
|
|
||||||
|
|
||||||
SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LPARAM) szBuf);
|
SendMessage(lpdis->hwndItem,LB_GETTEXT,lpdis->itemID,(LPARAM) szBuf);
|
||||||
ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+17,(int)(lpdis->rcItem.top),
|
ExtTextOut(lpdis->hDC,(int)(lpdis->rcItem.left)+17,(int)(lpdis->rcItem.top),
|
||||||
ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL);
|
ETO_OPAQUE,(LPRECT)&lpdis->rcItem,szBuf,lstrlen(szBuf),NULL);
|
||||||
|
|
||||||
SetBkColor(lpdis->hDC,crBkColor);
|
SetBkColor(lpdis->hDC,crBkColor); // restore color settings
|
||||||
SetTextColor(lpdis->hDC,crTextColor);
|
SetTextColor(lpdis->hDC,crTextColor);
|
||||||
|
|
||||||
// draw checkbox
|
// draw checkbox
|
||||||
i = (INT) SendMessage(lpdis->hwndItem,LB_GETITEMDATA,lpdis->itemID,0);
|
|
||||||
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
hdcMem = CreateCompatibleDC(lpdis->hDC);
|
||||||
_ASSERT(hBmpCheckBox);
|
_ASSERT(hBmpCheckBox);
|
||||||
hBmpOld = (HBITMAP) SelectObject(hdcMem,hBmpCheckBox);
|
hBmpOld = (HBITMAP) SelectObject(hdcMem,hBmpCheckBox);
|
||||||
|
|
||||||
BitBlt(lpdis->hDC,lpdis->rcItem.left+2,lpdis->rcItem.top+2,
|
BitBlt(lpdis->hDC,lpdis->rcItem.left+2,lpdis->rcItem.top+2,
|
||||||
11,lpdis->rcItem.bottom - lpdis->rcItem.top,
|
11,lpdis->rcItem.bottom - lpdis->rcItem.top,
|
||||||
hdcMem,sBreakpoint[i].bEnable ? 0 : 10,0,SRCCOPY);
|
hdcMem,sBreakpoint[lpdis->itemData].bEnable ? 0 : 10,0,SRCCOPY);
|
||||||
|
|
||||||
SelectObject(hdcMem,hBmpOld);
|
SelectObject(hdcMem,hBmpOld);
|
||||||
DeleteDC(hdcMem);
|
DeleteDC(hdcMem);
|
||||||
|
|
|
@ -425,8 +425,8 @@ static LPTSTR disasm_1 (DWORD *addr, LPTSTR out)
|
||||||
fn = read_nibble (addr);
|
fn = read_nibble (addr);
|
||||||
c = (fn < 8); // flag for operand register
|
c = (fn < 8); // flag for operand register
|
||||||
fn = (fn & 7); // get register number
|
fn = (fn & 7); // get register number
|
||||||
if (fn > 4) // illegal opcode
|
if (fn > 4) // unsupported opcode
|
||||||
break; // no output
|
fn -= 4; // map to valid scratch register
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
case HP_MNEMONICS:
|
||||||
|
@ -457,8 +457,8 @@ static LPTSTR disasm_1 (DWORD *addr, LPTSTR out)
|
||||||
fn = read_nibble (addr);
|
fn = read_nibble (addr);
|
||||||
c = (fn < 8); // flag for operand register
|
c = (fn < 8); // flag for operand register
|
||||||
fn = (fn & 7); // get register number
|
fn = (fn & 7); // get register number
|
||||||
if (fn > 4) // illegal opcode
|
if (fn > 4) // unsupported opcode
|
||||||
break; // no output
|
fn -= 4; // map to valid scratch register
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
case HP_MNEMONICS:
|
||||||
|
@ -680,6 +680,7 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out)
|
||||||
{
|
{
|
||||||
BYTE n;
|
BYTE n;
|
||||||
BYTE fn;
|
BYTE fn;
|
||||||
|
BYTE rn;
|
||||||
LPTSTR p = out;
|
LPTSTR p = out;
|
||||||
TCHAR c;
|
TCHAR c;
|
||||||
TCHAR buf[20];
|
TCHAR buf[20];
|
||||||
|
@ -975,48 +976,49 @@ static LPTSTR disasm_8 (DWORD *addr, LPTSTR out)
|
||||||
if (n > 2) // illegal opcode
|
if (n > 2) // illegal opcode
|
||||||
break; // no output
|
break; // no output
|
||||||
c = (TCHAR) read_nibble (addr);
|
c = (TCHAR) read_nibble (addr);
|
||||||
if (((int) c & 7) > 4) // illegal opcode
|
rn = (c & 7); // get register number
|
||||||
break; // no output
|
c = (c < 8); // flag for operand register
|
||||||
|
if (rn > 4) // unsupported opcode
|
||||||
|
rn -= 4; // map to valid scratch register
|
||||||
switch (disassembler_mode)
|
switch (disassembler_mode)
|
||||||
{
|
{
|
||||||
case HP_MNEMONICS:
|
case HP_MNEMONICS:
|
||||||
|
c = (TCHAR) (c ? _T('A') : _T('C'));
|
||||||
if (n == 2)
|
if (n == 2)
|
||||||
{
|
{
|
||||||
wsprintf (buf, _T("%cR%dEX.F"), ((int) c < 8) ? _T('A') : _T('C'),
|
wsprintf (buf, _T("%cR%dEX.F"), c, rn);
|
||||||
(int) c & 7);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
{
|
{
|
||||||
wsprintf (buf, _T("%c=R%d.F"), ((int) c < 8) ? _T('A') : _T('C'),
|
wsprintf (buf, _T("%c=R%d.F"), c, rn);
|
||||||
(int) c & 7);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wsprintf (buf, _T("R%d=%c.F"), (int) c & 7,
|
wsprintf (buf, _T("R%d=%c.F"), rn, c);
|
||||||
((int) c < 8) ? _T('A') : _T('C'));
|
|
||||||
}
|
}
|
||||||
p = append_str (out, buf);
|
p = append_str (out, buf);
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
p = append_field (p, fn);
|
p = append_field (p, fn);
|
||||||
break;
|
break;
|
||||||
case CLASS_MNEMONICS:
|
case CLASS_MNEMONICS:
|
||||||
|
c = (TCHAR) (c ? _T('a') : _T('c'));
|
||||||
p = append_str (out, (n == 2) ? _T("exg") : _T("move"));
|
p = append_str (out, (n == 2) ? _T("exg") : _T("move"));
|
||||||
p = append_field (p, fn);
|
p = append_field (p, fn);
|
||||||
p = append_tab (out);
|
p = append_tab (out);
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
{
|
{
|
||||||
wsprintf (buf, _T("r%d"), (int) c & 7);
|
wsprintf (buf, _T("r%d"), rn);
|
||||||
p = append_str (p, buf);
|
p = append_str (p, buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p = append_str (p, ((int) c < 8) ? _T("a") : _T("c"));
|
*p++ = c;
|
||||||
p = append_str (p, _T(", "));
|
p = append_str (p, _T(", "));
|
||||||
if (n == 1)
|
if (n == 1)
|
||||||
p = append_str (p, ((int) c < 8) ? _T("a") : _T("c"));
|
*p++ = c;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wsprintf (buf, _T("r%d"), (int) c & 7);
|
wsprintf (buf, _T("r%d"), rn);
|
||||||
p = append_str (p, buf);
|
p = append_str (p, buf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -373,10 +373,15 @@ VOID InitAdjustSpeed(VOID)
|
||||||
if (!bEnableSlow || (!bCpuSlow && !bKeySlow && !bSoundSlow && nOpcSlow == 0))
|
if (!bEnableSlow || (!bCpuSlow && !bKeySlow && !bSoundSlow && nOpcSlow == 0))
|
||||||
{
|
{
|
||||||
LARGE_INTEGER lTime; // sample timer ticks
|
LARGE_INTEGER lTime; // sample timer ticks
|
||||||
// save reference cycles
|
|
||||||
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
EnterCriticalSection(&csSlowLock);
|
||||||
QueryPerformanceCounter(&lTime); // get timer ticks
|
{
|
||||||
dwSpeedRef = lTime.LowPart; // save reference time
|
// save reference cycles
|
||||||
|
dwOldCyc = (DWORD) (Chipset.cycles & 0xFFFFFFFF);
|
||||||
|
QueryPerformanceCounter(&lTime);// get timer ticks
|
||||||
|
dwSpeedRef = lTime.LowPart; // save reference time
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&csSlowLock);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -390,29 +395,21 @@ VOID AdjKeySpeed(VOID) // slow down key repeat
|
||||||
for (i = 0;i < ARRAYSIZEOF(Chipset.Keyboard_Row) && !bKey;++i)
|
for (i = 0;i < ARRAYSIZEOF(Chipset.Keyboard_Row) && !bKey;++i)
|
||||||
bKey = (Chipset.Keyboard_Row[i] != 0);
|
bKey = (Chipset.Keyboard_Row[i] != 0);
|
||||||
|
|
||||||
EnterCriticalSection(&csSlowLock);
|
if (bKey) // key pressed
|
||||||
{
|
{
|
||||||
if (bKey) // key pressed
|
InitAdjustSpeed(); // init variables if necessary
|
||||||
{
|
|
||||||
InitAdjustSpeed(); // init variables if necessary
|
|
||||||
}
|
|
||||||
bKeySlow = bKey; // save new state
|
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&csSlowLock);
|
bKeySlow = bKey; // save new state
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
VOID SetSpeed(BOOL bAdjust) // set emulation speed
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&csSlowLock);
|
if (bAdjust) // switch to real speed
|
||||||
{
|
{
|
||||||
if (bAdjust) // switch to real speed
|
InitAdjustSpeed(); // init variables if necessary
|
||||||
{
|
|
||||||
InitAdjustSpeed(); // init variables if necessary
|
|
||||||
}
|
|
||||||
bCpuSlow = bAdjust; // save emulation speed
|
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&csSlowLock);
|
bCpuSlow = bAdjust; // save emulation speed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,17 +345,17 @@ static JMPTAB o81Af2_[] =
|
||||||
(LPCVOID) o81Af22, F,
|
(LPCVOID) o81Af22, F,
|
||||||
(LPCVOID) o81Af23, F,
|
(LPCVOID) o81Af23, F,
|
||||||
(LPCVOID) o81Af24, F,
|
(LPCVOID) o81Af24, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af21, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af22, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af23, F,
|
||||||
(LPCVOID) o81Af28, F,
|
(LPCVOID) o81Af28, F,
|
||||||
(LPCVOID) o81Af29, F,
|
(LPCVOID) o81Af29, F,
|
||||||
(LPCVOID) o81Af2A, F,
|
(LPCVOID) o81Af2A, F,
|
||||||
(LPCVOID) o81Af2B, F,
|
(LPCVOID) o81Af2B, F,
|
||||||
(LPCVOID) o81Af2C, F,
|
(LPCVOID) o81Af2C, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af29, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af2A, F,
|
||||||
(LPCVOID) o_invalid6, F
|
(LPCVOID) o81Af2B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o81Af1_[] =
|
static JMPTAB o81Af1_[] =
|
||||||
|
@ -365,17 +365,17 @@ static JMPTAB o81Af1_[] =
|
||||||
(LPCVOID) o81Af12, F,
|
(LPCVOID) o81Af12, F,
|
||||||
(LPCVOID) o81Af13, F,
|
(LPCVOID) o81Af13, F,
|
||||||
(LPCVOID) o81Af14, F,
|
(LPCVOID) o81Af14, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af11, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af12, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af13, F,
|
||||||
(LPCVOID) o81Af18, F,
|
(LPCVOID) o81Af18, F,
|
||||||
(LPCVOID) o81Af19, F,
|
(LPCVOID) o81Af19, F,
|
||||||
(LPCVOID) o81Af1A, F,
|
(LPCVOID) o81Af1A, F,
|
||||||
(LPCVOID) o81Af1B, F,
|
(LPCVOID) o81Af1B, F,
|
||||||
(LPCVOID) o81Af1C, F,
|
(LPCVOID) o81Af1C, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af19, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af1A, F,
|
||||||
(LPCVOID) o_invalid6, F
|
(LPCVOID) o81Af1B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o81Af0_[] =
|
static JMPTAB o81Af0_[] =
|
||||||
|
@ -385,17 +385,17 @@ static JMPTAB o81Af0_[] =
|
||||||
(LPCVOID) o81Af02, F,
|
(LPCVOID) o81Af02, F,
|
||||||
(LPCVOID) o81Af03, F,
|
(LPCVOID) o81Af03, F,
|
||||||
(LPCVOID) o81Af04, F,
|
(LPCVOID) o81Af04, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af01, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af02, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af03, F,
|
||||||
(LPCVOID) o81Af08, F,
|
(LPCVOID) o81Af08, F,
|
||||||
(LPCVOID) o81Af09, F,
|
(LPCVOID) o81Af09, F,
|
||||||
(LPCVOID) o81Af0A, F,
|
(LPCVOID) o81Af0A, F,
|
||||||
(LPCVOID) o81Af0B, F,
|
(LPCVOID) o81Af0B, F,
|
||||||
(LPCVOID) o81Af0C, F,
|
(LPCVOID) o81Af0C, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af09, F,
|
||||||
(LPCVOID) o_invalid6, F,
|
(LPCVOID) o81Af0A, F,
|
||||||
(LPCVOID) o_invalid6, F
|
(LPCVOID) o81Af0B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o81A_[] =
|
static JMPTAB o81A_[] =
|
||||||
|
@ -625,17 +625,17 @@ static JMPTAB o12_[] =
|
||||||
(LPCVOID) o122, F,
|
(LPCVOID) o122, F,
|
||||||
(LPCVOID) o123, F,
|
(LPCVOID) o123, F,
|
||||||
(LPCVOID) o124, F,
|
(LPCVOID) o124, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o121, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o122, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o123, F,
|
||||||
(LPCVOID) o128, F,
|
(LPCVOID) o128, F,
|
||||||
(LPCVOID) o129, F,
|
(LPCVOID) o129, F,
|
||||||
(LPCVOID) o12A, F,
|
(LPCVOID) o12A, F,
|
||||||
(LPCVOID) o12B, F,
|
(LPCVOID) o12B, F,
|
||||||
(LPCVOID) o12C, F,
|
(LPCVOID) o12C, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o129, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o12A, F,
|
||||||
(LPCVOID) o_invalid3, F
|
(LPCVOID) o12B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o11_[] =
|
static JMPTAB o11_[] =
|
||||||
|
@ -645,17 +645,17 @@ static JMPTAB o11_[] =
|
||||||
(LPCVOID) o112, F,
|
(LPCVOID) o112, F,
|
||||||
(LPCVOID) o113, F,
|
(LPCVOID) o113, F,
|
||||||
(LPCVOID) o114, F,
|
(LPCVOID) o114, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o111, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o112, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o113, F,
|
||||||
(LPCVOID) o118, F,
|
(LPCVOID) o118, F,
|
||||||
(LPCVOID) o119, F,
|
(LPCVOID) o119, F,
|
||||||
(LPCVOID) o11A, F,
|
(LPCVOID) o11A, F,
|
||||||
(LPCVOID) o11B, F,
|
(LPCVOID) o11B, F,
|
||||||
(LPCVOID) o11C, F,
|
(LPCVOID) o11C, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o119, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o11A, F,
|
||||||
(LPCVOID) o_invalid3, F
|
(LPCVOID) o11B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o10_[] =
|
static JMPTAB o10_[] =
|
||||||
|
@ -665,17 +665,17 @@ static JMPTAB o10_[] =
|
||||||
(LPCVOID) o102, F,
|
(LPCVOID) o102, F,
|
||||||
(LPCVOID) o103, F,
|
(LPCVOID) o103, F,
|
||||||
(LPCVOID) o104, F,
|
(LPCVOID) o104, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o101, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o102, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o103, F,
|
||||||
(LPCVOID) o108, F,
|
(LPCVOID) o108, F,
|
||||||
(LPCVOID) o109, F,
|
(LPCVOID) o109, F,
|
||||||
(LPCVOID) o10A, F,
|
(LPCVOID) o10A, F,
|
||||||
(LPCVOID) o10B, F,
|
(LPCVOID) o10B, F,
|
||||||
(LPCVOID) o10C, F,
|
(LPCVOID) o10C, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o109, F,
|
||||||
(LPCVOID) o_invalid3, F,
|
(LPCVOID) o10A, F,
|
||||||
(LPCVOID) o_invalid3, F
|
(LPCVOID) o10B, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static JMPTAB o1_[] =
|
static JMPTAB o1_[] =
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
LodePNG version 20200306
|
LodePNG version 20210627
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2021 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 = "20200306";
|
const char* LODEPNG_VERSION_STRING = "20210627";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This source file is built up in the following large parts. The code sections
|
This source file is built up in the following large parts. The code sections
|
||||||
|
@ -299,6 +299,7 @@ static void string_cleanup(char** out) {
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*also appends null termination character*/
|
||||||
static char* alloc_string_sized(const char* in, size_t insize) {
|
static char* alloc_string_sized(const char* in, size_t insize) {
|
||||||
char* out = (char*)lodepng_malloc(insize + 1);
|
char* out = (char*)lodepng_malloc(insize + 1);
|
||||||
if(out) {
|
if(out) {
|
||||||
|
@ -1260,7 +1261,7 @@ static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
|
||||||
|
|
||||||
/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
|
/*inflate a block with dynamic of fixed Huffman tree. btype must be 1 or 2.*/
|
||||||
static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
unsigned btype) {
|
unsigned btype, size_t max_output_size) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
|
HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
|
||||||
HuffmanTree tree_d; /*the huffman tree for distance codes*/
|
HuffmanTree tree_d; /*the huffman tree for distance codes*/
|
||||||
|
@ -1341,6 +1342,9 @@ static unsigned inflateHuffmanBlock(ucvector* out, LodePNGBitReader* reader,
|
||||||
/* TODO: revise error codes 10,11,50: the above comment is no longer valid */
|
/* TODO: revise error codes 10,11,50: the above comment is no longer valid */
|
||||||
ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
|
ERROR_BREAK(51); /*error, bit pointer jumps past memory*/
|
||||||
}
|
}
|
||||||
|
if(max_output_size && out->size > max_output_size) {
|
||||||
|
ERROR_BREAK(109); /*error, larger than max size*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HuffmanTree_cleanup(&tree_ll);
|
HuffmanTree_cleanup(&tree_ll);
|
||||||
|
@ -1398,9 +1402,9 @@ static unsigned lodepng_inflatev(ucvector* out,
|
||||||
|
|
||||||
if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
|
if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
|
||||||
else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
|
else if(BTYPE == 0) error = inflateNoCompression(out, &reader, settings); /*no compression*/
|
||||||
else error = inflateHuffmanBlock(out, &reader, BTYPE); /*compression, BTYPE 01 or 10*/
|
else error = inflateHuffmanBlock(out, &reader, BTYPE, settings->max_output_size); /*compression, BTYPE 01 or 10*/
|
||||||
|
if(!error && settings->max_output_size && out->size > settings->max_output_size) error = 109;
|
||||||
if(error) return error;
|
if(error) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -1421,6 +1425,12 @@ static unsigned inflatev(ucvector* out, const unsigned char* in, size_t insize,
|
||||||
if(settings->custom_inflate) {
|
if(settings->custom_inflate) {
|
||||||
unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
|
unsigned error = settings->custom_inflate(&out->data, &out->size, in, insize, settings);
|
||||||
out->allocsize = out->size;
|
out->allocsize = out->size;
|
||||||
|
if(error) {
|
||||||
|
/*the custom inflate is allowed to have its own error codes, however, we translate it to code 110*/
|
||||||
|
error = 110;
|
||||||
|
/*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
|
||||||
|
if(settings->max_output_size && out->size > settings->max_output_size) error = 109;
|
||||||
|
}
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_inflatev(out, in, insize, settings);
|
return lodepng_inflatev(out, in, insize, settings);
|
||||||
|
@ -2116,7 +2126,9 @@ static unsigned deflate(unsigned char** out, size_t* outsize,
|
||||||
const unsigned char* in, size_t insize,
|
const unsigned char* in, size_t insize,
|
||||||
const LodePNGCompressSettings* settings) {
|
const LodePNGCompressSettings* settings) {
|
||||||
if(settings->custom_deflate) {
|
if(settings->custom_deflate) {
|
||||||
return settings->custom_deflate(out, outsize, in, insize, settings);
|
unsigned error = settings->custom_deflate(out, outsize, in, insize, settings);
|
||||||
|
/*the custom deflate is allowed to have its own error codes, however, we translate it to code 111*/
|
||||||
|
return error ? 111 : 0;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_deflate(out, outsize, in, insize, settings);
|
return lodepng_deflate(out, outsize, in, insize, settings);
|
||||||
}
|
}
|
||||||
|
@ -2213,10 +2225,16 @@ unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const uns
|
||||||
/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
|
/*expected_size is expected output size, to avoid intermediate allocations. Set to 0 if not known. */
|
||||||
static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
|
static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
|
||||||
const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
|
const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
|
||||||
|
unsigned error;
|
||||||
if(settings->custom_zlib) {
|
if(settings->custom_zlib) {
|
||||||
return settings->custom_zlib(out, outsize, in, insize, settings);
|
error = settings->custom_zlib(out, outsize, in, insize, settings);
|
||||||
|
if(error) {
|
||||||
|
/*the custom zlib is allowed to have its own error codes, however, we translate it to code 110*/
|
||||||
|
error = 110;
|
||||||
|
/*if there's a max output size, and the custom zlib returned error, then indicate that error instead*/
|
||||||
|
if(settings->max_output_size && *outsize > settings->max_output_size) error = 109;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned error;
|
|
||||||
ucvector v = ucvector_init(*out, *outsize);
|
ucvector v = ucvector_init(*out, *outsize);
|
||||||
if(expected_size) {
|
if(expected_size) {
|
||||||
/*reserve the memory to avoid intermediate reallocations*/
|
/*reserve the memory to avoid intermediate reallocations*/
|
||||||
|
@ -2226,8 +2244,8 @@ static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t exp
|
||||||
error = lodepng_zlib_decompressv(&v, in, insize, settings);
|
error = lodepng_zlib_decompressv(&v, in, insize, settings);
|
||||||
*out = v.data;
|
*out = v.data;
|
||||||
*outsize = v.size;
|
*outsize = v.size;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
@ -2275,7 +2293,9 @@ unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsig
|
||||||
static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
|
static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
|
||||||
size_t insize, const LodePNGCompressSettings* settings) {
|
size_t insize, const LodePNGCompressSettings* settings) {
|
||||||
if(settings->custom_zlib) {
|
if(settings->custom_zlib) {
|
||||||
return settings->custom_zlib(out, outsize, in, insize, settings);
|
unsigned error = settings->custom_zlib(out, outsize, in, insize, settings);
|
||||||
|
/*the custom zlib is allowed to have its own error codes, however, we translate it to code 111*/
|
||||||
|
return error ? 111 : 0;
|
||||||
} else {
|
} else {
|
||||||
return lodepng_zlib_compress(out, outsize, in, insize, settings);
|
return lodepng_zlib_compress(out, outsize, in, insize, settings);
|
||||||
}
|
}
|
||||||
|
@ -2334,13 +2354,14 @@ const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT
|
||||||
void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
|
void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
|
||||||
settings->ignore_adler32 = 0;
|
settings->ignore_adler32 = 0;
|
||||||
settings->ignore_nlen = 0;
|
settings->ignore_nlen = 0;
|
||||||
|
settings->max_output_size = 0;
|
||||||
|
|
||||||
settings->custom_zlib = 0;
|
settings->custom_zlib = 0;
|
||||||
settings->custom_inflate = 0;
|
settings->custom_inflate = 0;
|
||||||
settings->custom_context = 0;
|
settings->custom_context = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0};
|
const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
#endif /*LODEPNG_COMPILE_DECODER*/
|
#endif /*LODEPNG_COMPILE_DECODER*/
|
||||||
|
|
||||||
|
@ -2872,8 +2893,8 @@ static void LodePNGText_cleanup(LodePNGInfo* info) {
|
||||||
|
|
||||||
static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
dest->text_keys = 0;
|
dest->text_keys = NULL;
|
||||||
dest->text_strings = 0;
|
dest->text_strings = NULL;
|
||||||
dest->text_num = 0;
|
dest->text_num = 0;
|
||||||
for(i = 0; i != source->text_num; ++i) {
|
for(i = 0; i != source->text_num; ++i) {
|
||||||
CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
|
CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
|
||||||
|
@ -2932,10 +2953,10 @@ static void LodePNGIText_cleanup(LodePNGInfo* info) {
|
||||||
|
|
||||||
static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
dest->itext_keys = 0;
|
dest->itext_keys = NULL;
|
||||||
dest->itext_langtags = 0;
|
dest->itext_langtags = NULL;
|
||||||
dest->itext_transkeys = 0;
|
dest->itext_transkeys = NULL;
|
||||||
dest->itext_strings = 0;
|
dest->itext_strings = NULL;
|
||||||
dest->itext_num = 0;
|
dest->itext_num = 0;
|
||||||
for(i = 0; i != source->itext_num; ++i) {
|
for(i = 0; i != source->itext_num; ++i) {
|
||||||
CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
|
CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
|
||||||
|
@ -4093,10 +4114,12 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
case 0:
|
case 0:
|
||||||
for(i = 0; i != length; ++i) recon[i] = scanline[i];
|
for(i = 0; i != length; ++i) recon[i] = scanline[i];
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1: {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
|
for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + recon[j];
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 2:
|
case 2:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
|
for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
|
||||||
|
@ -4106,24 +4129,56 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1u);
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1u);
|
/* Unroll independent paths of this predictor. A 6x and 8x version is also possible but that adds
|
||||||
|
too much code. Whether this speeds up anything depends on compiler and settings. */
|
||||||
|
if(bytewidth >= 4) {
|
||||||
|
for(; i + 3 < length; i += 4, j += 4) {
|
||||||
|
unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
|
||||||
|
unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
|
||||||
|
unsigned char s2 = scanline[i + 2], r2 = recon[j + 2], p2 = precon[i + 2];
|
||||||
|
unsigned char s3 = scanline[i + 3], r3 = recon[j + 3], p3 = precon[i + 3];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
recon[i + 2] = s2 + ((r2 + p2) >> 1u);
|
||||||
|
recon[i + 3] = s3 + ((r3 + p3) >> 1u);
|
||||||
|
}
|
||||||
|
} else if(bytewidth >= 3) {
|
||||||
|
for(; i + 2 < length; i += 3, j += 3) {
|
||||||
|
unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
|
||||||
|
unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
|
||||||
|
unsigned char s2 = scanline[i + 2], r2 = recon[j + 2], p2 = precon[i + 2];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
recon[i + 2] = s2 + ((r2 + p2) >> 1u);
|
||||||
|
}
|
||||||
|
} else if(bytewidth >= 2) {
|
||||||
|
for(; i + 1 < length; i += 2, j += 2) {
|
||||||
|
unsigned char s0 = scanline[i + 0], r0 = recon[j + 0], p0 = precon[i + 0];
|
||||||
|
unsigned char s1 = scanline[i + 1], r1 = recon[j + 1], p1 = precon[i + 1];
|
||||||
|
recon[i + 0] = s0 + ((r0 + p0) >> 1u);
|
||||||
|
recon[i + 1] = s1 + ((r1 + p1) >> 1u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(; i != length; ++i, ++j) recon[i] = scanline[i] + ((recon[j] + precon[i]) >> 1u);
|
||||||
} else {
|
} else {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
|
||||||
for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1u);
|
for(i = bytewidth; i != length; ++i, ++j) recon[i] = scanline[i] + (recon[j] >> 1u);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if(precon) {
|
if(precon) {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) {
|
for(i = 0; i != bytewidth; ++i) {
|
||||||
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
|
recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unroll independent paths of the paeth predictor. A 6x and 8x version would also be possible but that
|
/* Unroll independent paths of the paeth predictor. A 6x and 8x version is also possible but that
|
||||||
adds too much code. Whether this actually speeds anything up at all depends on compiler and settings. */
|
adds too much code. Whether this speeds up anything depends on compiler and settings. */
|
||||||
if(bytewidth >= 4) {
|
if(bytewidth >= 4) {
|
||||||
for(; i + 3 < length; i += 4) {
|
for(; i + 3 < length; i += 4, j += 4) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2], s3 = scanline[i + 3];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2], r3 = recon[j + 3];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2], p3 = precon[i + 3];
|
||||||
|
@ -4134,8 +4189,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
|
recon[i + 3] = s3 + paethPredictor(r3, p3, q3);
|
||||||
}
|
}
|
||||||
} else if(bytewidth >= 3) {
|
} else if(bytewidth >= 3) {
|
||||||
for(; i + 2 < length; i += 3) {
|
for(; i + 2 < length; i += 3, j += 3) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1], s2 = scanline[i + 2];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1], r2 = recon[j + 2];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1], p2 = precon[i + 2];
|
||||||
|
@ -4145,8 +4199,7 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
|
recon[i + 2] = s2 + paethPredictor(r2, p2, q2);
|
||||||
}
|
}
|
||||||
} else if(bytewidth >= 2) {
|
} else if(bytewidth >= 2) {
|
||||||
for(; i + 1 < length; i += 2) {
|
for(; i + 1 < length; i += 2, j += 2) {
|
||||||
size_t j = i - bytewidth;
|
|
||||||
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
|
unsigned char s0 = scanline[i + 0], s1 = scanline[i + 1];
|
||||||
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
|
unsigned char r0 = recon[j + 0], r1 = recon[j + 1];
|
||||||
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
|
unsigned char p0 = precon[i + 0], p1 = precon[i + 1];
|
||||||
|
@ -4156,16 +4209,17 @@ static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; i != length; ++i) {
|
for(; i != length; ++i, ++j) {
|
||||||
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
|
recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[j]));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
size_t j = 0;
|
||||||
for(i = 0; i != bytewidth; ++i) {
|
for(i = 0; i != bytewidth; ++i) {
|
||||||
recon[i] = scanline[i];
|
recon[i] = scanline[i];
|
||||||
}
|
}
|
||||||
for(i = bytewidth; i < length; ++i) {
|
for(i = bytewidth; i != length; ++i, ++j) {
|
||||||
/*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
|
/*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
|
||||||
recon[i] = (scanline[i] + recon[i - bytewidth]);
|
recon[i] = (scanline[i] + recon[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4447,10 +4501,13 @@ static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, siz
|
||||||
}
|
}
|
||||||
|
|
||||||
/*compressed text chunk (zTXt)*/
|
/*compressed text chunk (zTXt)*/
|
||||||
static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
|
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, string2_begin;
|
unsigned length, string2_begin;
|
||||||
char *key = 0;
|
char *key = 0;
|
||||||
unsigned char* str = 0;
|
unsigned char* str = 0;
|
||||||
|
@ -4473,12 +4530,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
|
||||||
|
|
||||||
length = (unsigned)chunkLength - string2_begin;
|
length = (unsigned)chunkLength - string2_begin;
|
||||||
|
zlibsettings.max_output_size = decoder->max_text_size;
|
||||||
/*will fail if zlib error, e.g. if length is too small*/
|
/*will fail if zlib error, e.g. if length is too small*/
|
||||||
error = zlib_decompress(&str, &size, 0, &data[string2_begin],
|
error = zlib_decompress(&str, &size, 0, &data[string2_begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: compressed text larger than decoder->max_text_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 112;
|
||||||
if(error) break;
|
if(error) break;
|
||||||
error = lodepng_add_text_sized(info, key, (char*)str, size);
|
error = lodepng_add_text_sized(info, key, (char*)str, size);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4489,11 +4548,14 @@ static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
}
|
}
|
||||||
|
|
||||||
/*international text chunk (iTXt)*/
|
/*international text chunk (iTXt)*/
|
||||||
static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, begin, compressed;
|
unsigned length, begin, compressed;
|
||||||
char *key = 0, *langtag = 0, *transkey = 0;
|
char *key = 0, *langtag = 0, *transkey = 0;
|
||||||
|
|
||||||
|
@ -4550,9 +4612,12 @@ static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(compressed) {
|
if(compressed) {
|
||||||
unsigned char* str = 0;
|
unsigned char* str = 0;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
zlibsettings.max_output_size = decoder->max_text_size;
|
||||||
/*will fail if zlib error, e.g. if length is too small*/
|
/*will fail if zlib error, e.g. if length is too small*/
|
||||||
error = zlib_decompress(&str, &size, 0, &data[begin],
|
error = zlib_decompress(&str, &size, 0, &data[begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: compressed text larger than decoder->max_text_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 112;
|
||||||
if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
|
if(!error) error = lodepng_add_itext_sized(info, key, langtag, transkey, (char*)str, size);
|
||||||
lodepng_free(str);
|
lodepng_free(str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -4628,11 +4693,13 @@ static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, siz
|
||||||
return 0; /* OK */
|
return 0; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
|
static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecoderSettings* decoder,
|
||||||
const unsigned char* data, size_t chunkLength) {
|
const unsigned char* data, size_t chunkLength) {
|
||||||
unsigned error = 0;
|
unsigned error = 0;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
/*copy the object to change parameters in it*/
|
||||||
|
LodePNGDecompressSettings zlibsettings = decoder->zlibsettings;
|
||||||
|
|
||||||
unsigned length, string2_begin;
|
unsigned length, string2_begin;
|
||||||
|
|
||||||
|
@ -4655,9 +4722,12 @@ static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSetting
|
||||||
if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
|
if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
|
||||||
|
|
||||||
length = (unsigned)chunkLength - string2_begin;
|
length = (unsigned)chunkLength - string2_begin;
|
||||||
|
zlibsettings.max_output_size = decoder->max_icc_size;
|
||||||
error = zlib_decompress(&info->iccp_profile, &size, 0,
|
error = zlib_decompress(&info->iccp_profile, &size, 0,
|
||||||
&data[string2_begin],
|
&data[string2_begin],
|
||||||
length, zlibsettings);
|
length, &zlibsettings);
|
||||||
|
/*error: ICC profile larger than decoder->max_icc_size*/
|
||||||
|
if(error && size > zlibsettings.max_output_size) error = 113;
|
||||||
info->iccp_profile_size = (unsigned)size;
|
info->iccp_profile_size = (unsigned)size;
|
||||||
if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
|
if(!error && !info->iccp_profile_size) error = 100; /*invalid ICC profile size*/
|
||||||
return error;
|
return error;
|
||||||
|
@ -4688,9 +4758,9 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
|
||||||
error = readChunk_tEXt(&state->info_png, data, chunkLength);
|
error = readChunk_tEXt(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
||||||
error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
||||||
error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
||||||
error = readChunk_tIME(&state->info_png, data, chunkLength);
|
error = readChunk_tIME(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
|
} else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
|
||||||
|
@ -4702,7 +4772,7 @@ unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
|
} else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
|
||||||
error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||||
error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} else {
|
} else {
|
||||||
/* unhandled chunk is ok (is not an error) */
|
/* unhandled chunk is ok (is not an error) */
|
||||||
|
@ -4820,13 +4890,13 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
|
||||||
/*compressed text chunk (zTXt)*/
|
/*compressed text chunk (zTXt)*/
|
||||||
if(state->decoder.read_text_chunks) {
|
if(state->decoder.read_text_chunks) {
|
||||||
state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_zTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
}
|
}
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
|
||||||
/*international text chunk (iTXt)*/
|
/*international text chunk (iTXt)*/
|
||||||
if(state->decoder.read_text_chunks) {
|
if(state->decoder.read_text_chunks) {
|
||||||
state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_iTXt(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
}
|
}
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
} else if(lodepng_chunk_type_equals(chunk, "tIME")) {
|
||||||
|
@ -4845,7 +4915,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
} else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
|
||||||
state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
|
state->error = readChunk_iCCP(&state->info_png, &state->decoder, data, chunkLength);
|
||||||
if(state->error) break;
|
if(state->error) break;
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
|
} else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
|
||||||
|
@ -4871,7 +4941,7 @@ static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
|
if(!IEND) chunk = lodepng_chunk_next_const(chunk, in + insize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
|
if(!state->error && state->info_png.color.colortype == LCT_PALETTE && !state->info_png.color.palette) {
|
||||||
state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
|
state->error = 106; /* error: PNG file must have PLTE chunk if color type is palette */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4955,6 +5025,11 @@ unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, co
|
||||||
lodepng_state_init(&state);
|
lodepng_state_init(&state);
|
||||||
state.info_raw.colortype = colortype;
|
state.info_raw.colortype = colortype;
|
||||||
state.info_raw.bitdepth = bitdepth;
|
state.info_raw.bitdepth = bitdepth;
|
||||||
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
|
/*disable reading things that this function doesn't output*/
|
||||||
|
state.decoder.read_text_chunks = 0;
|
||||||
|
state.decoder.remember_unknown_chunks = 0;
|
||||||
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
error = lodepng_decode(out, w, h, &state, in, insize);
|
error = lodepng_decode(out, w, h, &state, in, insize);
|
||||||
lodepng_state_cleanup(&state);
|
lodepng_state_cleanup(&state);
|
||||||
return error;
|
return error;
|
||||||
|
@ -4997,6 +5072,8 @@ void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
|
||||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
settings->read_text_chunks = 1;
|
settings->read_text_chunks = 1;
|
||||||
settings->remember_unknown_chunks = 0;
|
settings->remember_unknown_chunks = 0;
|
||||||
|
settings->max_text_size = 16777216;
|
||||||
|
settings->max_icc_size = 16777216; /* 16MB is much more than enough for any reasonable ICC profile */
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
settings->ignore_crc = 0;
|
settings->ignore_crc = 0;
|
||||||
settings->ignore_critical = 0;
|
settings->ignore_critical = 0;
|
||||||
|
@ -6204,6 +6281,16 @@ const char* lodepng_error_text(unsigned code) {
|
||||||
case 106: return "PNG file must have PLTE chunk if color type is palette";
|
case 106: return "PNG file must have PLTE chunk if color type is palette";
|
||||||
case 107: return "color convert from palette mode requested without setting the palette data in it";
|
case 107: return "color convert from palette mode requested without setting the palette data in it";
|
||||||
case 108: return "tried to add more than 256 values to a palette";
|
case 108: return "tried to add more than 256 values to a palette";
|
||||||
|
/*this limit can be configured in LodePNGDecompressSettings*/
|
||||||
|
case 109: return "tried to decompress zlib or deflate data larger than desired max_output_size";
|
||||||
|
case 110: return "custom zlib or inflate decompression failed";
|
||||||
|
case 111: return "custom zlib or deflate compression failed";
|
||||||
|
/*max text size limit can be configured in LodePNGDecoderSettings. This error prevents
|
||||||
|
unreasonable memory consumption when decoding due to impossibly large text sizes.*/
|
||||||
|
case 112: return "compressed text unreasonably large";
|
||||||
|
/*max ICC size limit can be configured in LodePNGDecoderSettings. This error prevents
|
||||||
|
unreasonable memory consumption when decoding due to impossibly large ICC profile*/
|
||||||
|
case 113: return "ICC profile unreasonably large";
|
||||||
}
|
}
|
||||||
return "unknown error code";
|
return "unknown error code";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
LodePNG version 20200306
|
LodePNG version 20210627
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2021 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
|
||||||
|
@ -142,16 +142,24 @@ unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
/*
|
/*
|
||||||
Load PNG from disk, from file with given name.
|
Load PNG from disk, from file with given name.
|
||||||
Same as the other decode functions, but instead takes a filename as input.
|
Same as the other decode functions, but instead takes a filename as input.
|
||||||
*/
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
LodePNGColorType colortype, unsigned bitdepth);
|
LodePNGColorType colortype, unsigned bitdepth);
|
||||||
|
|
||||||
/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/
|
/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename);
|
const char* filename);
|
||||||
|
|
||||||
/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/
|
/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.*/
|
||||||
unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
|
unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
|
||||||
const char* filename);
|
const char* filename);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -191,17 +199,26 @@ unsigned lodepng_encode24(unsigned char** out, size_t* outsize,
|
||||||
/*
|
/*
|
||||||
Converts raw pixel data into a PNG file on disk.
|
Converts raw pixel data into a PNG file on disk.
|
||||||
Same as the other encode functions, but instead takes a filename as output.
|
Same as the other encode functions, but instead takes a filename as output.
|
||||||
|
|
||||||
NOTE: This overwrites existing files without warning!
|
NOTE: This overwrites existing files without warning!
|
||||||
*/
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode_file(const char* filename,
|
unsigned lodepng_encode_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h,
|
const unsigned char* image, unsigned w, unsigned h,
|
||||||
LodePNGColorType colortype, unsigned bitdepth);
|
LodePNGColorType colortype, unsigned bitdepth);
|
||||||
|
|
||||||
/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/
|
/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode32_file(const char* filename,
|
unsigned lodepng_encode32_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h);
|
const unsigned char* image, unsigned w, unsigned h);
|
||||||
|
|
||||||
/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/
|
/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory.*/
|
||||||
unsigned lodepng_encode24_file(const char* filename,
|
unsigned lodepng_encode24_file(const char* filename,
|
||||||
const unsigned char* image, unsigned w, unsigned h);
|
const unsigned char* image, unsigned w, unsigned h);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -223,6 +240,9 @@ unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||||
/*
|
/*
|
||||||
Converts PNG file from disk to raw pixel data in memory.
|
Converts PNG file from disk to raw pixel data in memory.
|
||||||
Same as the other decode functions, but instead takes a filename as input.
|
Same as the other decode functions, but instead takes a filename as input.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
|
@ -243,7 +263,11 @@ unsigned encode(std::vector<unsigned char>& out,
|
||||||
/*
|
/*
|
||||||
Converts 32-bit RGBA raw pixel data into a PNG file on disk.
|
Converts 32-bit RGBA raw pixel data into a PNG file on disk.
|
||||||
Same as the other encode functions, but instead takes a filename as output.
|
Same as the other encode functions, but instead takes a filename as output.
|
||||||
|
|
||||||
NOTE: This overwrites existing files without warning!
|
NOTE: This overwrites existing files without warning!
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned encode(const std::string& filename,
|
unsigned encode(const std::string& filename,
|
||||||
const unsigned char* in, unsigned w, unsigned h,
|
const unsigned char* in, unsigned w, unsigned h,
|
||||||
|
@ -270,12 +294,21 @@ struct LodePNGDecompressSettings {
|
||||||
unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
|
unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
|
||||||
unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
|
unsigned ignore_nlen; /*ignore complement of len checksum in uncompressed blocks*/
|
||||||
|
|
||||||
/*use custom zlib decoder instead of built in one (default: null)*/
|
/*Maximum decompressed size, beyond this the decoder may (and is encouraged to) stop decoding,
|
||||||
|
return an error, output a data size > max_output_size and all the data up to that point. This is
|
||||||
|
not hard limit nor a guarantee, but can prevent excessive memory usage. This setting is
|
||||||
|
ignored by the PNG decoder, but is used by the deflate/zlib decoder and can be used by custom ones.
|
||||||
|
Set to 0 to impose no limit (the default).*/
|
||||||
|
size_t max_output_size;
|
||||||
|
|
||||||
|
/*use custom zlib decoder instead of built in one (default: null).
|
||||||
|
Should return 0 if success, any non-0 if error (numeric value not exposed).*/
|
||||||
unsigned (*custom_zlib)(unsigned char**, size_t*,
|
unsigned (*custom_zlib)(unsigned char**, size_t*,
|
||||||
const unsigned char*, size_t,
|
const unsigned char*, size_t,
|
||||||
const LodePNGDecompressSettings*);
|
const LodePNGDecompressSettings*);
|
||||||
/*use custom deflate decoder instead of built in one (default: null)
|
/*use custom deflate decoder instead of built in one (default: null)
|
||||||
if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate)*/
|
if custom_zlib is not null, custom_inflate is ignored (the zlib format uses deflate).
|
||||||
|
Should return 0 if success, any non-0 if error (numeric value not exposed).*/
|
||||||
unsigned (*custom_inflate)(unsigned char**, size_t*,
|
unsigned (*custom_inflate)(unsigned char**, size_t*,
|
||||||
const unsigned char*, size_t,
|
const unsigned char*, size_t,
|
||||||
const LodePNGDecompressSettings*);
|
const LodePNGDecompressSettings*);
|
||||||
|
@ -454,30 +487,36 @@ typedef struct LodePNGInfo {
|
||||||
unsigned background_b; /*blue component of suggested background color*/
|
unsigned background_b; /*blue component of suggested background color*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
non-international text chunks (tEXt and zTXt)
|
Non-international text chunks (tEXt and zTXt)
|
||||||
|
|
||||||
The char** arrays each contain num strings. The actual messages are in
|
The char** arrays each contain num strings. The actual messages are in
|
||||||
text_strings, while text_keys are keywords that give a short description what
|
text_strings, while text_keys are keywords that give a short description what
|
||||||
the actual text represents, e.g. Title, Author, Description, or anything else.
|
the actual text represents, e.g. Title, Author, Description, or anything else.
|
||||||
|
|
||||||
All the string fields below including keys, names and language tags are null terminated.
|
All the string fields below including strings, keys, names and language tags are null terminated.
|
||||||
The PNG specification uses null characters for the keys, names and tags, and forbids null
|
The PNG specification uses null characters for the keys, names and tags, and forbids null
|
||||||
characters to appear in the main text which is why we can use null termination everywhere here.
|
characters to appear in the main text which is why we can use null termination everywhere here.
|
||||||
|
|
||||||
A keyword is minimum 1 character and maximum 79 characters long. It's
|
A keyword is minimum 1 character and maximum 79 characters long (plus the
|
||||||
discouraged to use a single line length longer than 79 characters for texts.
|
additional null terminator). It's discouraged to use a single line length
|
||||||
|
longer than 79 characters for texts.
|
||||||
|
|
||||||
Don't allocate these text buffers yourself. Use the init/cleanup functions
|
Don't allocate these text buffers yourself. Use the init/cleanup functions
|
||||||
correctly and use lodepng_add_text and lodepng_clear_text.
|
correctly and use lodepng_add_text and lodepng_clear_text.
|
||||||
|
|
||||||
|
Standard text chunk keywords and strings are encoded using Latin-1.
|
||||||
*/
|
*/
|
||||||
size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
|
size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
|
||||||
char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
|
char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
|
||||||
char** text_strings; /*the actual text*/
|
char** text_strings; /*the actual text*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
international text chunks (iTXt)
|
International text chunks (iTXt)
|
||||||
Similar to the non-international text chunks, but with additional strings
|
Similar to the non-international text chunks, but with additional strings
|
||||||
"langtags" and "transkeys".
|
"langtags" and "transkeys", and the following text encodings are used:
|
||||||
|
keys: Latin-1, langtags: ASCII, transkeys and strings: UTF-8.
|
||||||
|
keys must be 1-79 characters (plus the additional null terminator), the other
|
||||||
|
strings are any length.
|
||||||
*/
|
*/
|
||||||
size_t itext_num; /*the amount of international texts in this PNG*/
|
size_t itext_num; /*the amount of international texts in this PNG*/
|
||||||
char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
|
char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
|
||||||
|
@ -639,8 +678,19 @@ typedef struct LodePNGDecoderSettings {
|
||||||
|
|
||||||
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
|
||||||
unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
|
unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
|
||||||
|
|
||||||
/*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
|
/*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
|
||||||
unsigned remember_unknown_chunks;
|
unsigned remember_unknown_chunks;
|
||||||
|
|
||||||
|
/* maximum size for decompressed text chunks. If a text chunk's text is larger than this, an error is returned,
|
||||||
|
unless reading text chunks is disabled or this limit is set higher or disabled. Set to 0 to allow any size.
|
||||||
|
By default it is a value that prevents unreasonably large strings from hogging memory. */
|
||||||
|
size_t max_text_size;
|
||||||
|
|
||||||
|
/* maximum size for compressed ICC chunks. If the ICC profile is larger than this, an error will be returned. Set to
|
||||||
|
0 to allow any size. By default this is a value that prevents ICC profiles that would be much larger than any
|
||||||
|
legitimate profile could be to hog memory. */
|
||||||
|
size_t max_icc_size;
|
||||||
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
|
||||||
} LodePNGDecoderSettings;
|
} LodePNGDecoderSettings;
|
||||||
|
|
||||||
|
@ -950,6 +1000,9 @@ out: output parameter, contains pointer to loaded buffer.
|
||||||
outsize: output parameter, size of the allocated out buffer
|
outsize: output parameter, size of the allocated out buffer
|
||||||
filename: the path to the file to load
|
filename: the path to the file to load
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory.
|
||||||
*/
|
*/
|
||||||
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
|
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
|
||||||
|
|
||||||
|
@ -960,6 +1013,9 @@ buffer: the buffer to write
|
||||||
buffersize: size of the buffer to write
|
buffersize: size of the buffer to write
|
||||||
filename: the path to the file to save to
|
filename: the path to the file to save to
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
|
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
|
||||||
#endif /*LODEPNG_COMPILE_DISK*/
|
#endif /*LODEPNG_COMPILE_DISK*/
|
||||||
|
@ -1000,12 +1056,18 @@ unsigned encode(std::vector<unsigned char>& out,
|
||||||
/*
|
/*
|
||||||
Load a file from disk into an std::vector.
|
Load a file from disk into an std::vector.
|
||||||
return value: error code (0 means ok)
|
return value: error code (0 means ok)
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and decode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Save the binary data in an std::vector to a file on disk. The file is overwritten
|
Save the binary data in an std::vector to a file on disk. The file is overwritten
|
||||||
without warning.
|
without warning.
|
||||||
|
|
||||||
|
NOTE: Wide-character filenames are not supported, you can use an external method
|
||||||
|
to handle such files and encode in-memory
|
||||||
*/
|
*/
|
||||||
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
|
||||||
#endif /* LODEPNG_COMPILE_DISK */
|
#endif /* LODEPNG_COMPILE_DISK */
|
||||||
|
@ -1505,6 +1567,11 @@ of the error in English as a string.
|
||||||
|
|
||||||
Check the implementation of lodepng_error_text to see the meaning of each code.
|
Check the implementation of lodepng_error_text to see the meaning of each code.
|
||||||
|
|
||||||
|
It is not recommended to use the numerical values to programmatically make
|
||||||
|
different decisions based on error types as the numbers are not guaranteed to
|
||||||
|
stay backwards compatible. They are for human consumption only. Programmatically
|
||||||
|
only 0 or non-0 matter.
|
||||||
|
|
||||||
|
|
||||||
8. chunks and PNG editing
|
8. chunks and PNG editing
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@ -1678,6 +1745,9 @@ try to fix it if the compiler is modern and standards compliant.
|
||||||
This decoder example shows the most basic usage of LodePNG. More complex
|
This decoder example shows the most basic usage of LodePNG. More complex
|
||||||
examples can be found on the LodePNG website.
|
examples can be found on the LodePNG website.
|
||||||
|
|
||||||
|
NOTE: these examples do not support wide-character filenames, you can use an
|
||||||
|
external method to handle such files and encode or decode in-memory
|
||||||
|
|
||||||
10.1. decoder C++ example
|
10.1. decoder C++ example
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -1775,6 +1845,10 @@ 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
|
||||||
|
|
||||||
|
*) 27 jun 2021: added warnings that file reading/writing functions don't support
|
||||||
|
wide-character filenames (support for this is not planned, opening files is
|
||||||
|
not the core part of PNG decoding/decoding and is platform dependent).
|
||||||
|
*) 17 okt 2020: prevent decoding too large text/icc chunks by default.
|
||||||
*) 06 mar 2020: simplified some of the dynamic memory allocations.
|
*) 06 mar 2020: simplified some of the dynamic memory allocations.
|
||||||
*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
|
*) 12 jan 2020: (!) added 'end' argument to lodepng_chunk_next to allow correct
|
||||||
overflow checks.
|
overflow checks.
|
||||||
|
@ -1941,5 +2015,5 @@ Domain: gmail dot com.
|
||||||
Account: lode dot vandevenne.
|
Account: lode dot vandevenne.
|
||||||
|
|
||||||
|
|
||||||
Copyright (c) 2005-2020 Lode Vandevenne
|
Copyright (c) 2005-2021 Lode Vandevenne
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1009,9 +1009,9 @@ static DWORD ReadT2Acc(VOID)
|
||||||
// maybe CPU speed measurement, slow down the next 10 CPU opcodes
|
// maybe CPU speed measurement, slow down the next 10 CPU opcodes
|
||||||
if (dwCycDif < 150)
|
if (dwCycDif < 150)
|
||||||
{
|
{
|
||||||
|
InitAdjustSpeed(); // init variables if necessary
|
||||||
EnterCriticalSection(&csSlowLock);
|
EnterCriticalSection(&csSlowLock);
|
||||||
{
|
{
|
||||||
InitAdjustSpeed(); // init variables if necessary
|
|
||||||
nOpcSlow = 10; // slow down next 10 opcodes
|
nOpcSlow = 10; // slow down next 10 opcodes
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&csSlowLock);
|
LeaveCriticalSection(&csSlowLock);
|
||||||
|
|
|
@ -504,21 +504,13 @@ VOID SoundOut(CHIPSET* w, WORD wOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ran out of buffers -> disable CPU slow down
|
// ran out of buffers -> disable CPU slow down
|
||||||
EnterCriticalSection(&csSlowLock);
|
InitAdjustSpeed(); // init variables if necessary
|
||||||
{
|
bEnableSlow = (GetSoundBufSize() > 1);
|
||||||
InitAdjustSpeed(); // init variables if necessary
|
|
||||||
bEnableSlow = (GetSoundBufSize() > 1);
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&csSlowLock);
|
|
||||||
|
|
||||||
if (bSoundSlow == FALSE)
|
if (bSoundSlow == FALSE)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&csSlowLock);
|
InitAdjustSpeed(); // init variables if necessary
|
||||||
{
|
bSoundSlow = TRUE; // CPU slow down
|
||||||
InitAdjustSpeed(); // init variables if necessary
|
|
||||||
bSoundSlow = TRUE; // CPU slow down
|
|
||||||
}
|
|
||||||
LeaveCriticalSection(&csSlowLock);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ buildscript {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.2'
|
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
Loading…
Reference in a new issue