From efd3625e65c4d8488bac3e484e4cddf825cf179d Mon Sep 17 00:00:00 2001 From: Chance4us <45902449+Chance4us@users.noreply.github.com> Date: Thu, 8 Oct 2020 16:58:29 +0200 Subject: [PATCH] experimental xbrz filtering (#714) --- .travis.yml | 2 +- CMakeLists.txt | 14 +- Source/all.h | 8 - Source/appfat.h | 12 + Source/automap.h | 12 + Source/capture.h | 12 + Source/codec.h | 12 + Source/control.cpp | 8 +- Source/control.h | 12 + Source/cursor.h | 12 + Source/dead.h | 12 + Source/debug.h | 12 + Source/diablo.cpp | 2 + Source/diablo.h | 12 + Source/doom.h | 12 + Source/drlg_l1.h | 12 + Source/drlg_l2.h | 12 + Source/drlg_l3.h | 12 + Source/drlg_l4.h | 12 + Source/dthread.h | 11 + Source/dx.h | 11 + Source/effects.h | 11 + Source/encrypt.h | 12 + Source/engine.h | 12 + Source/error.h | 12 + Source/gamemenu.h | 12 + Source/gendung.h | 12 + Source/gmenu.h | 12 + Source/help.h | 12 + Source/init.h | 12 + Source/interfac.h | 12 + Source/inv.h | 12 + Source/itemdat.h | 12 + Source/items.cpp | 4 +- Source/items.h | 12 + Source/lighting.h | 12 + Source/loadsave.h | 12 + Source/mainmenu.cpp | 8 +- Source/mainmenu.h | 14 +- Source/minitext.h | 12 + Source/misdat.h | 12 + Source/missiles.h | 12 + Source/monstdat.h | 12 + Source/monster.h | 12 + Source/movie.h | 12 + Source/mpqapi.h | 12 + Source/msg.h | 12 + Source/multi.h | 12 + Source/nthread.h | 11 + Source/objdat.h | 12 + Source/objects.h | 12 + Source/pack.h | 11 + Source/palette.h | 12 + Source/path.h | 12 + Source/pfile.h | 11 + Source/player.h | 12 + Source/plrmsg.h | 12 + Source/portal.cpp | 2 +- Source/portal.h | 12 + Source/quests.h | 12 + Source/render.h | 12 + Source/restrict.h | 12 + Source/scrollrt.cpp | 8 +- Source/scrollrt.h | 12 + Source/setmaps.cpp | 2 +- Source/setmaps.h | 12 + Source/sha.h | 12 + Source/sound.h | 12 + Source/spelldat.h | 12 + Source/spells.h | 12 + Source/stores.h | 11 + Source/sync.h | 12 + Source/textdat.h | 12 + Source/themes.cpp | 8 +- Source/themes.h | 12 + Source/tmsg.h | 12 + Source/town.h | 12 + Source/towners.cpp | 52 +- Source/towners.h | 13 +- Source/track.cpp | 2 +- Source/track.h | 12 + Source/trigs.cpp | 48 +- Source/trigs.h | 12 + Source/wave.h | 12 + SourceX/DiabloUI/credits.cpp | 15 +- SourceX/DiabloUI/credits_lines.cpp | 867 +++++++++--------- SourceX/DiabloUI/fonts.cpp | 2 +- SourceX/display.cpp | 13 +- SourceX/dx.cpp | 99 +- SourceX/filters/xbrz/Changelog.txt | 66 ++ SourceX/filters/xbrz/License.txt | 622 +++++++++++++ SourceX/filters/xbrz/xbrz.cpp | 1363 ++++++++++++++++++++++++++++ SourceX/filters/xbrz/xbrz.h | 79 ++ SourceX/filters/xbrz/xbrz_config.h | 35 + SourceX/filters/xbrz/xbrz_tools.h | 274 ++++++ SourceX/miniwin/misc_msg.cpp | 38 + SourceX/storm/storm.cpp | 8 +- defs.h | 2 + enums.h | 4 + structs.h | 4 + types.h | 2 - 101 files changed, 3968 insertions(+), 529 deletions(-) create mode 100644 SourceX/filters/xbrz/Changelog.txt create mode 100644 SourceX/filters/xbrz/License.txt create mode 100644 SourceX/filters/xbrz/xbrz.cpp create mode 100644 SourceX/filters/xbrz/xbrz.h create mode 100644 SourceX/filters/xbrz/xbrz_config.h create mode 100644 SourceX/filters/xbrz/xbrz_tools.h diff --git a/.travis.yml b/.travis.yml index b1eaa39ca..bc1f90784 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,4 +41,4 @@ deploy: skip_cleanup: true on: tags: true - condition: "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_CPU_ARCH" == "ppc64le" + condition: $TRAVIS_OS_NAME == "linux" && $TRAVIS_CPU_ARCH == "ppc64le" diff --git a/CMakeLists.txt b/CMakeLists.txt index ab42c8b9a..cb73bf3ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ include(CMake/genex.cmake) DEBUG_OPTION(ASAN "Enable address sanitizer") DEBUG_OPTION(UBSAN "Enable undefined behaviour sanitizer") DEBUG_OPTION(DEBUG "Enable debug mode in engine") -option(DISABLE_LTO "Disable link-time optimization (by default enabled in release mode)" OFF) +option(DISABLE_LTO "Disable link-time optimization (by default enabled in release mode)" ON) option(PIE "Generate position-independent code" OFF) option(SPAWN "Build the shareware version" OFF) option(DIST "Dynamically link only glibc and SDL2" OFF) @@ -37,9 +37,14 @@ if(NOT VERSION_NUM) endif() endif() -project(DevilutionX - VERSION ${VERSION_NUM} - LANGUAGES C CXX) +if(VERSION_NUM MATCHES untagged) + project(DevilutionX + LANGUAGES C CXX) +else() + project(DevilutionX + VERSION ${VERSION_NUM} + LANGUAGES C CXX) +endif() # Not a genexp because CMake doesn't support it # https://gitlab.kitware.com/cmake/cmake/-/issues/20546 @@ -232,6 +237,7 @@ add_library(devilution STATIC Source/wave.cpp) set(devilutionx_SRCS + SourceX/filters/xbrz/xbrz.cpp SourceX/dx.cpp SourceX/controls/devices/game_controller.cpp SourceX/controls/devices/joystick.cpp diff --git a/Source/all.h b/Source/all.h index 72b21c4e4..30abce1f6 100644 --- a/Source/all.h +++ b/Source/all.h @@ -18,9 +18,6 @@ #include "../types.h" -#ifdef __cplusplus -extern "C" { -#endif #include "appfat.h" #include "automap.h" #include "capture.h" @@ -91,10 +88,5 @@ extern "C" { #include "trigs.h" #include "wave.h" #include "render.h" // linked last, likely .s/.asm -#ifdef __cplusplus -} -#endif - -DEVILUTION_END_NAMESPACE #endif /* __ALL_H__ */ diff --git a/Source/appfat.h b/Source/appfat.h index 6200d6a03..f7d06af05 100644 --- a/Source/appfat.h +++ b/Source/appfat.h @@ -6,6 +6,12 @@ #ifndef __APPFAT_H__ #define __APPFAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern char sz_error_buf[256]; extern BOOL terminating; extern int cleanup_thread_id; @@ -30,4 +36,10 @@ void DiskFreeDlg(char *error); void InsertCDDlg(const char *fileName); void DirErrorDlg(char *error); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __APPFAT_H__ */ diff --git a/Source/automap.h b/Source/automap.h index 219b0e74b..49cc6d307 100644 --- a/Source/automap.h +++ b/Source/automap.h @@ -6,6 +6,12 @@ #ifndef __AUTOMAP_H__ #define __AUTOMAP_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern WORD automaptype[512]; extern BOOL automapflag; extern char AmShiftTab[31]; @@ -36,4 +42,10 @@ void DrawAutomapText(); void SetAutomapView(int x, int y); void AutomapZoomReset(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __AUTOMAP_H__ */ diff --git a/Source/capture.h b/Source/capture.h index 9a54e2d11..fa8d0934d 100644 --- a/Source/capture.h +++ b/Source/capture.h @@ -6,6 +6,18 @@ #ifndef __CAPTURE_H__ #define __CAPTURE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void CaptureScreen(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __CAPTURE_H__ */ diff --git a/Source/codec.h b/Source/codec.h index 00c11ceab..caf929337 100644 --- a/Source/codec.h +++ b/Source/codec.h @@ -6,9 +6,21 @@ #ifndef __CODEC_H__ #define __CODEC_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + int codec_decode(BYTE *pbSrcDst, DWORD size, char *pszPassword); void codec_init_key(int unused, char *pszPassword); DWORD codec_get_encoded_len(DWORD dwSrcBytes); void codec_encode(BYTE *pbSrcDst, DWORD size, int size_64, char *pszPassword); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __CODEC_H__ */ diff --git a/Source/control.cpp b/Source/control.cpp index 6c637093a..8625a2214 100644 --- a/Source/control.cpp +++ b/Source/control.cpp @@ -659,7 +659,7 @@ void DrawLifeFlask() filled = 11; filled += 2; - DrawFlask(pLifeBuff, 88, 277, gpBuffer, SCREENXY(PANEL_LEFT + 109, PANEL_TOP - 13), filled); + DrawFlask(pLifeBuff, 88, 88 * 3 + 13, gpBuffer, SCREENXY(PANEL_LEFT + 109, PANEL_TOP - 13), filled); if (filled != 13) DrawFlask(pBtmBuff, PANEL_WIDTH, PANEL_WIDTH * (filled + 3) + 109, gpBuffer, SCREENXY(PANEL_LEFT + 109, PANEL_TOP - 13 + filled), 13 - filled); } @@ -697,7 +697,7 @@ void DrawManaFlask() filled = 11; filled += 2; - DrawFlask(pManaBuff, 88, 277, gpBuffer, SCREENXY(PANEL_LEFT + 475, PANEL_TOP - 13), filled); + DrawFlask(pManaBuff, 88, 88 * 3 + 13, gpBuffer, SCREENXY(PANEL_LEFT + 475, PANEL_TOP - 13), filled); if (filled != 13) DrawFlask(pBtmBuff, PANEL_WIDTH, PANEL_WIDTH * (filled + 3) + 475, gpBuffer, SCREENXY(PANEL_LEFT + 475, PANEL_TOP - 13 + filled), 13 - filled); } @@ -743,9 +743,9 @@ void UpdateManaFlask() if (filled > 69) filled = 69; if (filled != 69) - SetFlaskHeight(pManaBuff, 16, 85 - filled, 96 + PANEL_X + 368, PANEL_Y); + SetFlaskHeight(pManaBuff, 16, 85 - filled, PANEL_X + 464, PANEL_Y); if (filled != 0) - DrawPanelBox(96 + 368, 85 - filled, 88, filled, 96 + PANEL_X + 368, PANEL_Y + 69 - filled); + DrawPanelBox(464, 85 - filled, 88, filled, PANEL_X + 464, PANEL_Y + 69 - filled); DrawSpell(); } diff --git a/Source/control.h b/Source/control.h index 65e3be261..2266f3200 100644 --- a/Source/control.h +++ b/Source/control.h @@ -6,6 +6,12 @@ #ifndef __CONTROL_H__ #define __CONTROL_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE *pDurIcons; extern BYTE *pChrButtons; extern BOOL drawhpflag; @@ -137,4 +143,10 @@ extern char *PanBtnStr[8]; extern RECT32 ChrBtnsRect[4]; extern int SpellPages[6][7]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __CONTROL_H__ */ diff --git a/Source/cursor.h b/Source/cursor.h index 42da1ff94..3c77c428e 100644 --- a/Source/cursor.h +++ b/Source/cursor.h @@ -6,6 +6,12 @@ #ifndef __CURSOR_H__ #define __CURSOR_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int cursW; extern int cursH; extern int pcursmonst; @@ -37,4 +43,10 @@ void CheckCursMove(); extern const int InvItemWidth[]; extern const int InvItemHeight[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __CURSOR_H__ */ diff --git a/Source/dead.h b/Source/dead.h index f9e992a22..16c3c5243 100644 --- a/Source/dead.h +++ b/Source/dead.h @@ -6,6 +6,12 @@ #ifndef __DEAD_H__ #define __DEAD_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int spurtndx; extern DeadStruct dead[MAXDEAD]; extern int stonendx; @@ -14,4 +20,10 @@ void InitDead(); void AddDead(int dx, int dy, char dv, int ddir); void SetDead(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DEAD_H__ */ diff --git a/Source/debug.h b/Source/debug.h index 1fee72aa8..1a210a41e 100644 --- a/Source/debug.h +++ b/Source/debug.h @@ -6,6 +6,12 @@ #ifndef __DEBUG_H__ #define __DEBUG_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE *pSquareCel; extern char dMonsDbg[NUMLEVELS][MAXDUNX][MAXDUNY]; extern char dFlagDbg[NUMLEVELS][MAXDUNX][MAXDUNY]; @@ -27,4 +33,10 @@ void GetDebugMonster(); void NextDebugMonster(); #endif +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DEBUG_H__ */ diff --git a/Source/diablo.cpp b/Source/diablo.cpp index 255637f5d..244c5a605 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -890,6 +890,7 @@ void PressKey(int vkey) diablo_hotkey_msg(3); } if (vkey == VK_RETURN) { + if (GetAsyncKeyState(VK_MENU) & 0x8000) dx_reinit(); control_type_message(); } if (vkey != VK_ESCAPE) { @@ -1099,6 +1100,7 @@ void PressChar(int vkey) return; } if (PauseMode == 2) { + if (GetAsyncKeyState(VK_MENU) & 0x8000) dx_reinit(); return; } if (doomflag) { diff --git a/Source/diablo.h b/Source/diablo.h index c16f6272f..98d4a258c 100644 --- a/Source/diablo.h +++ b/Source/diablo.h @@ -6,6 +6,12 @@ #ifndef __DIABLO_H__ #define __DIABLO_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern SDL_Window *ghMainWnd; extern DWORD glSeedTbl[NUMLEVELS]; extern int gnLevelTypeTbl[NUMLEVELS]; @@ -103,4 +109,10 @@ extern BOOL FriendlyMode; extern char *spszMsgTbl[4]; extern char *spszMsgHotKeyTbl[4]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DIABLO_H__ */ diff --git a/Source/doom.h b/Source/doom.h index b72b2c331..30ca5f034 100644 --- a/Source/doom.h +++ b/Source/doom.h @@ -6,6 +6,12 @@ #ifndef __DOOM_H__ #define __DOOM_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int doom_quest_time; extern int doom_stars_drawn; extern BYTE *pDoomCel; @@ -24,4 +30,10 @@ void doom_init(); void doom_close(); void doom_draw(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DOOM_H__ */ diff --git a/Source/drlg_l1.h b/Source/drlg_l1.h index 616cb4449..a63b22db3 100644 --- a/Source/drlg_l1.h +++ b/Source/drlg_l1.h @@ -6,6 +6,12 @@ #ifndef __DRLG_L1_H__ #define __DRLG_L1_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE L5dungeon[80][80]; extern BYTE L5dflags[DMAXX][DMAXY]; extern BOOL L5setloadflag; @@ -38,4 +44,10 @@ extern const BYTE PWATERIN[]; /* data */ extern BYTE L5ConvTbl[16]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DRLG_L1_H__ */ diff --git a/Source/drlg_l2.h b/Source/drlg_l2.h index c0a7a0184..5fdb0a188 100644 --- a/Source/drlg_l2.h +++ b/Source/drlg_l2.h @@ -6,6 +6,12 @@ #ifndef __DRLG_L2_H__ #define __DRLG_L2_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int nSx1; extern int nSy1; extern int nSx2; @@ -145,4 +151,10 @@ extern BYTE CTRDOOR7[]; extern BYTE CTRDOOR8[]; extern int Patterns[100][10]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DRLG_L2_H__ */ diff --git a/Source/drlg_l3.h b/Source/drlg_l3.h index a3067300a..7e75b32e9 100644 --- a/Source/drlg_l3.h +++ b/Source/drlg_l3.h @@ -6,6 +6,12 @@ #ifndef __DRLG_L3_H__ #define __DRLG_L3_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOLEAN lavapool; extern int abyssx; extern int lockoutcnt; @@ -61,4 +67,10 @@ extern const BYTE L3XTRA4[4]; extern const BYTE L3XTRA5[4]; extern const BYTE L3ANVIL[244]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DRLG_L3_H__ */ diff --git a/Source/drlg_l4.h b/Source/drlg_l4.h index 87d0a9028..ef1463bbe 100644 --- a/Source/drlg_l4.h +++ b/Source/drlg_l4.h @@ -6,6 +6,12 @@ #ifndef __DRLG_L4_H__ #define __DRLG_L4_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int diabquad1x; extern int diabquad1y; extern int diabquad2x; @@ -49,4 +55,10 @@ extern const BYTE L4PENTA[52]; extern const BYTE L4PENTA2[52]; extern const BYTE L4BTYPES[140]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __DRLG_L4_H__ */ diff --git a/Source/dthread.h b/Source/dthread.h index 78501ad34..a695ccbc6 100644 --- a/Source/dthread.h +++ b/Source/dthread.h @@ -6,6 +6,12 @@ #ifndef __DTHREAD_H__ #define __DTHREAD_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern SDL_threadID glpDThreadId; extern BOOLEAN dthread_running; @@ -16,5 +22,10 @@ unsigned int dthread_handler(void *data); void dthread_cleanup(); /* data */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __DTHREAD_H__ */ diff --git a/Source/dx.h b/Source/dx.h index f6beb4cd8..f91206209 100644 --- a/Source/dx.h +++ b/Source/dx.h @@ -6,6 +6,12 @@ #ifndef __DX_H__ #define __DX_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE *gpBuffer; extern char gbBackBuf; extern char gbEmulate; @@ -25,5 +31,10 @@ void PaletteGetEntries(DWORD dwNumEntries, SDL_Color *lpEntries); void PaletteSetEntries(DWORD dwCount, SDL_Color *lpEntries); /* data */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __DX_H__ */ diff --git a/Source/effects.h b/Source/effects.h index 7fc8d2110..7c09ce4ce 100644 --- a/Source/effects.h +++ b/Source/effects.h @@ -6,6 +6,12 @@ #ifndef __EFFECTS_H__ #define __EFFECTS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int sfxdelay; extern int sfxdnum; extern HANDLE sghStream; @@ -37,5 +43,10 @@ void effects_play_sound(char *snd_file); extern const char MonstSndChar[]; /* data */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __EFFECTS_H__ */ diff --git a/Source/encrypt.h b/Source/encrypt.h index adf86a765..561acb1c5 100644 --- a/Source/encrypt.h +++ b/Source/encrypt.h @@ -6,6 +6,12 @@ #ifndef __ENCRYPT_H__ #define __ENCRYPT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern DWORD hashtable[5][256]; void Decrypt(DWORD *castBlock, DWORD size, DWORD key); @@ -17,4 +23,10 @@ unsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param); void PkwareBufferWrite(char *buf, unsigned int *size, void *param); void PkwareDecompress(BYTE *pbInBuff, int recv_size, int dwMaxBytes); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __ENCRYPT_H__ */ diff --git a/Source/engine.h b/Source/engine.h index 0b58c971e..8811043ae 100644 --- a/Source/engine.h +++ b/Source/engine.h @@ -13,6 +13,12 @@ #ifndef __ENGINE_H__ #define __ENGINE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + //offset 0 //pCelBuff->pFrameTable[0] @@ -98,4 +104,10 @@ void PlayInGameMovie(char *pszMovie); extern const int RndInc; extern const int RndMult; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __ENGINE_H__ */ diff --git a/Source/error.h b/Source/error.h index adc7d6bac..49b2a9f89 100644 --- a/Source/error.h +++ b/Source/error.h @@ -6,6 +6,12 @@ #ifndef __ERROR_H__ #define __ERROR_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern char msgtable[MAX_SEND_STR_LEN]; extern DWORD msgdelay; extern char msgflag; @@ -18,4 +24,10 @@ void DrawDiabloMsg(); /* data */ extern char *MsgStrings[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __ERROR_H__ */ diff --git a/Source/gamemenu.h b/Source/gamemenu.h index 55ca4c409..d39630a22 100644 --- a/Source/gamemenu.h +++ b/Source/gamemenu.h @@ -6,6 +6,12 @@ #ifndef __GAMEMENU_H__ #define __GAMEMENU_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void gamemenu_on(); void gamemenu_update_single(TMenuItem *pMenuItems); void gamemenu_update_multi(TMenuItem *pMenuItems); @@ -35,4 +41,10 @@ extern char *music_toggle_names[]; extern char *sound_toggle_names[]; extern char *color_cycling_toggle_names[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __GAMEMENU_H__ */ diff --git a/Source/gendung.h b/Source/gendung.h index 9dd6b43be..8ff64e282 100644 --- a/Source/gendung.h +++ b/Source/gendung.h @@ -6,6 +6,12 @@ #ifndef __GENDUNG_H__ #define __GENDUNG_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE dungeon[DMAXX][DMAXY]; extern BYTE pdungeon[DMAXX][DMAXY]; extern char dflags[DMAXX][DMAXY]; @@ -89,4 +95,10 @@ void DRLG_HoldThemeRooms(); BOOL SkipThemeRoom(int x, int y); void InitLevels(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __GENDUNG_H__ */ diff --git a/Source/gmenu.h b/Source/gmenu.h index 2f028b214..336b85ec6 100644 --- a/Source/gmenu.h +++ b/Source/gmenu.h @@ -6,6 +6,12 @@ #ifndef __GMENU_H__ #define __GMENU_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE *optbar_cel; extern BOOLEAN mouseNavigation; extern BYTE *PentSpin_cel; @@ -43,4 +49,10 @@ void gmenu_slider_steps(TMenuItem *pItem, int dwTicks); extern const BYTE lfontframe[]; extern const BYTE lfontkern[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __GMENU_H__ */ diff --git a/Source/help.h b/Source/help.h index 52fb3bf36..75e60446f 100644 --- a/Source/help.h +++ b/Source/help.h @@ -6,6 +6,12 @@ #ifndef __HELP_H__ #define __HELP_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int help_select_line; extern int dword_634494; extern BOOL helpflag; @@ -22,4 +28,10 @@ void HelpScrollDown(); /* rdata */ extern const char gszHelpText[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __HELP_H__ */ diff --git a/Source/init.h b/Source/init.h index 1955fe51d..6c33f488c 100644 --- a/Source/init.h +++ b/Source/init.h @@ -6,6 +6,12 @@ #ifndef __INIT_H__ #define __INIT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern _SNETVERSIONDATA fileinfo; extern int gbActive; extern char diablo_exe_path[MAX_PATH]; @@ -36,4 +42,10 @@ extern BOOL was_window_init; /** defined in dx.cpp */ extern char gszVersionNumber[MAX_PATH]; extern char gszProductName[MAX_PATH]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __INIT_H__ */ diff --git a/Source/interfac.h b/Source/interfac.h index a88a864ea..e0835732c 100644 --- a/Source/interfac.h +++ b/Source/interfac.h @@ -6,6 +6,12 @@ #ifndef __INTERFAC_H__ #define __INTERFAC_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int progress_id; void interface_msg_pump(); @@ -21,4 +27,10 @@ void InitCutscene(unsigned int uMsg); extern const BYTE BarColor[3]; extern const int BarPos[3][2]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __INTERFAC_H__ */ diff --git a/Source/inv.h b/Source/inv.h index 672d452b0..779d9c0ef 100644 --- a/Source/inv.h +++ b/Source/inv.h @@ -6,6 +6,12 @@ #ifndef __INV_H__ #define __INV_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL invflag; extern BOOL drawsbarflag; extern const InvXY InvRect[73]; @@ -55,4 +61,10 @@ BOOL DropItemBeforeTrig(); extern int AP2x2Tbl[10]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __INV_H__ */ diff --git a/Source/itemdat.h b/Source/itemdat.h index 7d038985d..f67e826fa 100644 --- a/Source/itemdat.h +++ b/Source/itemdat.h @@ -6,9 +6,21 @@ #ifndef __ITEMDAT_H__ #define __ITEMDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern ItemDataStruct AllItemsList[]; extern const PLStruct PL_Prefix[]; extern const PLStruct PL_Suffix[]; extern const UItemStruct UniqueItemList[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __ITEMDAT_H__ */ diff --git a/Source/items.cpp b/Source/items.cpp index 195edb20d..01f6e4380 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1444,7 +1444,7 @@ void SaveItemPower(int i, int power, int param1, int param2, int minval, int max break; case IPL_SPELL: item[i]._iSpell = param1; - item[i]._iCharges = param1; + item[i]._iCharges = param1; // BUGFIX: should be param2. This code was correct in v1.04, and the bug was introduced between 1.04 and 1.09b. item[i]._iMaxCharges = param2; break; case IPL_FIREDAM: @@ -1697,7 +1697,7 @@ void GetItemPower(int i, int minlvl, int maxlvl, int flgs, BOOL onlygood) } } } - if (nl != 0) { + if (nt != 0) { preidx = l[random_(23, nt)]; sprintf(istr, "%s %s", PL_Prefix[preidx].PLName, item[i]._iIName); strcpy(item[i]._iIName, istr); diff --git a/Source/items.h b/Source/items.h index 274560154..6d43bd70f 100644 --- a/Source/items.h +++ b/Source/items.h @@ -6,6 +6,12 @@ #ifndef __ITEMS_H__ #define __ITEMS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int itemactive[MAXITEMS]; extern BOOL uitemflag; extern int itemavail[MAXITEMS]; @@ -140,4 +146,10 @@ extern int ItemInvSnds[]; extern int idoppely; extern int premiumlvladd[6]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __ITEMS_H__ */ diff --git a/Source/lighting.h b/Source/lighting.h index 49fee6928..bceb0e80d 100644 --- a/Source/lighting.h +++ b/Source/lighting.h @@ -6,6 +6,12 @@ #ifndef __LIGHTING_H__ #define __LIGHTING_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern LightListStruct VisionList[MAXVISION]; extern BYTE lightactive[MAXLIGHTS]; extern LightListStruct LightList[MAXLIGHTS]; @@ -56,4 +62,10 @@ extern BYTE vCrawlTable[23][30]; extern BYTE byte_49463C[18][18]; extern BYTE RadiusAdj[23]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __LIGHTING_H__ */ diff --git a/Source/loadsave.h b/Source/loadsave.h index c8d3f0db1..2ff97c212 100644 --- a/Source/loadsave.h +++ b/Source/loadsave.h @@ -6,6 +6,12 @@ #ifndef __LOADSAVE_H__ #define __LOADSAVE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE *tbuff; void LoadGame(BOOL firstflag); @@ -45,4 +51,10 @@ void SavePortal(int i); void SaveLevel(); void LoadLevel(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __LOADSAVE_H__ */ diff --git a/Source/mainmenu.cpp b/Source/mainmenu.cpp index 357ebe98f..eb99b06cd 100644 --- a/Source/mainmenu.cpp +++ b/Source/mainmenu.cpp @@ -34,7 +34,7 @@ void mainmenu_change_name(int arg1, int arg2, int arg3, int arg4, char *name_1, pfile_rename_hero(name_1, name_2); } -int mainmenu_select_hero_dialog( +BOOL mainmenu_select_hero_dialog( const _SNETPROGRAMDATA *client_info, const _SNETPLAYERDATA *user_info, const _SNETUIDATA *ui_info, @@ -74,7 +74,7 @@ int mainmenu_select_hero_dialog( } if (dlgresult == SELHERO_PREVIOUS) { SErrSetLastError(1223); - return 0; + return FALSE; } pfile_create_player_description(cdesc, cdlen); @@ -87,7 +87,7 @@ int mainmenu_select_hero_dialog( if (cname && clen) SStrCopy(cname, gszHero, clen); - return 1; + return TRUE; } void mainmenu_loop() @@ -128,7 +128,7 @@ void mainmenu_loop() done = TRUE; break; } - } while (done == FALSE); + } while (!done); music_stop(); } diff --git a/Source/mainmenu.h b/Source/mainmenu.h index b2b10770b..80b9bccdf 100644 --- a/Source/mainmenu.h +++ b/Source/mainmenu.h @@ -6,11 +6,17 @@ #ifndef __MAINMENU_H__ #define __MAINMENU_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern char gszHero[16]; void mainmenu_refresh_music(); void mainmenu_change_name(int arg1, int arg2, int arg3, int arg4, char *name_1, char *name_2); -int mainmenu_select_hero_dialog( +BOOL mainmenu_select_hero_dialog( const _SNETPROGRAMDATA *client_info, const _SNETPLAYERDATA *user_info, const _SNETUIDATA *ui_info, @@ -31,4 +37,10 @@ void mainmenu_play_intro(); extern int menu_music_track_id; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MAINMENU_H__ */ diff --git a/Source/minitext.h b/Source/minitext.h index 27b740e5c..e9ff0cd36 100644 --- a/Source/minitext.h +++ b/Source/minitext.h @@ -6,6 +6,12 @@ #ifndef __MINITEXT_H__ #define __MINITEXT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int qtexty; extern char *qtextptr; extern BOOLEAN qtextflag; @@ -28,4 +34,10 @@ extern const BYTE mfontkern[56]; extern int qscroll_spd_tbl[9]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MINITEXT_H__ */ diff --git a/Source/misdat.h b/Source/misdat.h index bab38abd1..0744f640d 100644 --- a/Source/misdat.h +++ b/Source/misdat.h @@ -6,7 +6,19 @@ #ifndef __MISDAT_H__ #define __MISDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern MissileData missiledata[]; extern MisFileData misfiledata[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MISDAT_H__ */ diff --git a/Source/missiles.h b/Source/missiles.h index ddd67ec96..941110d56 100644 --- a/Source/missiles.h +++ b/Source/missiles.h @@ -6,6 +6,12 @@ #ifndef __MISSILES_H__ #define __MISSILES_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int missileactive[MAXMISSILES]; extern int missileavail[MAXMISSILES]; extern MissileStruct missile[MAXMISSILES]; @@ -155,4 +161,10 @@ void ClearMissileSpot(int mi); extern int XDirAdd[8]; extern int YDirAdd[8]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MISSILES_H__ */ diff --git a/Source/monstdat.h b/Source/monstdat.h index 28de9975f..35738ac03 100644 --- a/Source/monstdat.h +++ b/Source/monstdat.h @@ -6,9 +6,21 @@ #ifndef __MONSTDAT_H__ #define __MONSTDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern MonsterData monsterdata[]; extern BYTE MonstConvTbl[]; extern BYTE MonstAvailTbl[]; extern UniqMonstStruct UniqMonst[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MONSTDAT_H__ */ diff --git a/Source/monster.h b/Source/monster.h index d0eaa3683..7ba21589d 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -6,6 +6,12 @@ #ifndef __MONSTER_H__ #define __MONSTER_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int MissileFileFlag; extern int monstkills[MAXMONSTERS]; extern int monstactive[MAXMONSTERS]; @@ -189,4 +195,10 @@ extern int rnd60[4]; extern void (*AiProc[])(int i); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MONSTER_H__ */ diff --git a/Source/movie.h b/Source/movie.h index e8b70a4fa..9c4e2a1b7 100644 --- a/Source/movie.h +++ b/Source/movie.h @@ -6,6 +6,12 @@ #ifndef __MOVIE_H__ #define __MOVIE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE movie_playing; extern BOOL loop_movie; @@ -14,4 +20,10 @@ LRESULT MovieWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); /* rdata */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MOVIE_H__ */ diff --git a/Source/mpqapi.h b/Source/mpqapi.h index de809b7f9..608dea57b 100644 --- a/Source/mpqapi.h +++ b/Source/mpqapi.h @@ -7,6 +7,13 @@ #define __MPQAPI_H__ #include + +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE mpq_buf[4096]; extern BOOL save_archive_modified; extern BOOLEAN save_archive_open; @@ -28,5 +35,10 @@ BOOL mpqapi_flush_and_close(const char *pszArchive, BOOL bFree, DWORD dwChar); /* rdata */ /* data */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __MPQAPI_H__ */ diff --git a/Source/msg.h b/Source/msg.h index 8dfeb7690..15aedd112 100644 --- a/Source/msg.h +++ b/Source/msg.h @@ -6,6 +6,12 @@ #ifndef __MSG_H__ #define __MSG_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL deltaload; extern BYTE gbBufferMsgs; extern int dwRecCount; @@ -146,4 +152,10 @@ DWORD On_NOVA(TCmd *pCmd, int pnum); DWORD On_SETSHIELD(TCmd *pCmd, int pnum); DWORD On_REMSHIELD(TCmd *pCmd, int pnum); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MSG_H__ */ diff --git a/Source/multi.h b/Source/multi.h index fbef671eb..754374dd6 100644 --- a/Source/multi.h +++ b/Source/multi.h @@ -6,6 +6,12 @@ #ifndef __MULTI_H__ #define __MULTI_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOLEAN gbSomebodyWonGameKludge; extern char szPlayerDescript[128]; extern WORD sgwPackPlrOffsetTbl[MAX_PLRS]; @@ -60,4 +66,10 @@ void recv_plrinfo(int pnum, TCmdPlrInfoHdr *p, BOOL recv); extern const int event_types[3]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __MULTI_H__ */ diff --git a/Source/nthread.h b/Source/nthread.h index 34e4600d8..c416e6cd5 100644 --- a/Source/nthread.h +++ b/Source/nthread.h @@ -6,6 +6,12 @@ #ifndef __NTHREAD_H__ #define __NTHREAD_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BYTE sgbNetUpdateRate; extern DWORD gdwMsgLenTbl[MAX_PLRS]; extern DWORD gdwDeltaBytesSec; @@ -30,5 +36,10 @@ void nthread_ignore_mutex(BOOL bStart); BOOL nthread_has_500ms_passed(BOOL unused); /* rdata */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __NTHREAD_H__ */ diff --git a/Source/objdat.h b/Source/objdat.h index 29c33bc19..a0f00b09c 100644 --- a/Source/objdat.h +++ b/Source/objdat.h @@ -2,8 +2,20 @@ #ifndef __OBJDAT_H__ #define __OBJDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int ObjTypeConv[]; extern ObjDataStruct AllObjects[99]; extern char *ObjMasterLoadList[56]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __OBJDAT_H__ */ diff --git a/Source/objects.h b/Source/objects.h index 8dc5059d2..bb2e95100 100644 --- a/Source/objects.h +++ b/Source/objects.h @@ -2,6 +2,12 @@ #ifndef __OBJECTS_H__ #define __OBJECTS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int trapid; extern int trapdir; extern BYTE *pObjCels[40]; @@ -163,4 +169,10 @@ extern BYTE shrineavail[NUM_SHRINETYPE]; extern char *StoryBookName[9]; extern int StoryText[3][3]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __OBJECTS_H__ */ diff --git a/Source/pack.h b/Source/pack.h index 5b7b6f6f1..87f601893 100644 --- a/Source/pack.h +++ b/Source/pack.h @@ -2,10 +2,21 @@ #ifndef __PACK_H__ #define __PACK_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void PackPlayer(PkPlayerStruct *pPack, int pnum, BOOL manashield); void VerifyGoldSeeds(PlayerStruct *pPlayer); void UnPackPlayer(PkPlayerStruct *pPack, int pnum, BOOL killok); /* rdata */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __PACK_H__ */ diff --git a/Source/palette.h b/Source/palette.h index 8d07c1df4..91f863481 100644 --- a/Source/palette.h +++ b/Source/palette.h @@ -2,6 +2,12 @@ #ifndef __PALETTE_H__ #define __PALETTE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern SDL_Color logical_palette[256]; extern SDL_Color system_palette[256]; extern SDL_Color orig_palette[256]; @@ -32,4 +38,10 @@ BOOL palette_set_color_cycling(BOOL enabled); extern int gamma_correction; extern BOOL color_cycling_enabled; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __PALETTE_H__ */ diff --git a/Source/path.h b/Source/path.h index 83191d34f..dfc25062f 100644 --- a/Source/path.h +++ b/Source/path.h @@ -6,6 +6,12 @@ #ifndef __PATH_H__ #define __PATH_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern PATHNODE path_nodes[MAXPATHNODES]; extern int gdwCurPathStep; extern int gdwCurNodes; @@ -38,4 +44,10 @@ extern const char pathydir[8]; /* data */ extern char path_directions[9]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __PATH_H__ */ diff --git a/Source/pfile.h b/Source/pfile.h index d47dc518b..a49080635 100644 --- a/Source/pfile.h +++ b/Source/pfile.h @@ -2,6 +2,12 @@ #ifndef __PFILE_H__ #define __PFILE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL gbValidSaveFile; void pfile_init_save_directory(); @@ -42,5 +48,10 @@ BYTE *pfile_read(const char *pszName, DWORD *pdwLen); void pfile_update(BOOL force_save); /* rdata */ +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __PFILE_H__ */ diff --git a/Source/player.h b/Source/player.h index bc6943b7f..f97a12ebe 100644 --- a/Source/player.h +++ b/Source/player.h @@ -2,6 +2,12 @@ #ifndef __PLAYER_H__ #define __PLAYER_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int plr_lframe_size; extern int plr_wframe_size; extern BYTE plr_gfx_flag; @@ -135,4 +141,10 @@ extern int ExpLvlsTbl[MAXCHARLEVEL]; extern char *ClassStrTbl[]; extern BYTE fix[9]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __PLAYER_H__ */ diff --git a/Source/plrmsg.h b/Source/plrmsg.h index 0cccbf51f..121576da2 100644 --- a/Source/plrmsg.h +++ b/Source/plrmsg.h @@ -2,6 +2,12 @@ #ifndef __PLRMSG_H__ #define __PLRMSG_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern _plrmsg plr_msgs[PMSG_COUNT]; void plrmsg_delay(BOOL delay); @@ -17,4 +23,10 @@ void PrintPlrMsg(DWORD x, DWORD y, DWORD width, const char *str, BYTE col); extern const char text_color_from_player_num[MAX_PLRS + 1]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __PLRMSG_H__ */ diff --git a/Source/portal.cpp b/Source/portal.cpp index 25fa6e579..8fc6e2cd7 100644 --- a/Source/portal.cpp +++ b/Source/portal.cpp @@ -111,7 +111,7 @@ void RemovePortalMissile(int id) dFlags[missile[mi]._mix][missile[mi]._miy] &= ~BFLAG_MISSILE; dMissile[missile[mi]._mix][missile[mi]._miy] = 0; - if (portal[id].level) + if (portal[id].level != 0) AddUnLight(missile[mi]._mlid); DeleteMissile(mi, i); diff --git a/Source/portal.h b/Source/portal.h index 1690180dc..5f8b25097 100644 --- a/Source/portal.h +++ b/Source/portal.h @@ -2,6 +2,12 @@ #ifndef __PORTAL_H__ #define __PORTAL_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern PortalStruct portal[MAXPORTAL]; extern int portalindex; @@ -23,4 +29,10 @@ BOOL PosOkPortal(int lvl, int x, int y); extern int WarpDropX[MAXPORTAL]; extern int WarpDropY[MAXPORTAL]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __PORTAL_H__ */ diff --git a/Source/quests.h b/Source/quests.h index cf52fb578..5bb10701c 100644 --- a/Source/quests.h +++ b/Source/quests.h @@ -2,6 +2,12 @@ #ifndef __QUESTS_H__ #define __QUESTS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int qtopline; extern BOOL questlog; extern BYTE *pQLogCel; @@ -52,4 +58,10 @@ extern int QuestGroup2[3]; extern int QuestGroup3[3]; extern int QuestGroup4[2]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __QUESTS_H__ */ diff --git a/Source/render.h b/Source/render.h index 0d3f60e9f..c80fcad97 100644 --- a/Source/render.h +++ b/Source/render.h @@ -1,8 +1,20 @@ #ifndef __RENDER_H__ #define __RENDER_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void RenderTile(BYTE *pBuff); void world_draw_black_tile(int sx, int sy); void trans_rect(int sx, int sy, int width, int height); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __RENDER_H__ */ diff --git a/Source/restrict.h b/Source/restrict.h index bb1d05567..b7584ccff 100644 --- a/Source/restrict.h +++ b/Source/restrict.h @@ -2,6 +2,18 @@ #ifndef __RESTRICT_H__ #define __RESTRICT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void ReadOnlyTest(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __RESTRICT_H__ */ diff --git a/Source/scrollrt.cpp b/Source/scrollrt.cpp index 22df76a74..cba470bd6 100644 --- a/Source/scrollrt.cpp +++ b/Source/scrollrt.cpp @@ -1261,8 +1261,8 @@ static void DrawMain(int dwHgt, BOOL draw_desc, BOOL draw_hp, BOOL draw_mana, BO } assert(ysize >= 0 && ysize <= SCREEN_HEIGHT); - - if (ysize > 0) { +/* comment out because of panel rendering issues*/ + /*if (ysize > 0) { DoBlitScreen(0, 0, SCREEN_WIDTH, ysize); } if (ysize < SCREEN_HEIGHT) { @@ -1293,7 +1293,9 @@ static void DrawMain(int dwHgt, BOOL draw_desc, BOOL draw_hp, BOOL draw_mana, BO if (sgdwCursWdt != 0) { DoBlitScreen(sgdwCursX, sgdwCursY, sgdwCursWdt, sgdwCursHgt); } - } + }*/ + /*instead blitting everything on surface with slight decrease of performance*/ + DoBlitScreen(0, 0, 640, 480); } /** diff --git a/Source/scrollrt.h b/Source/scrollrt.h index 7ceca2adc..eb455e43c 100644 --- a/Source/scrollrt.h +++ b/Source/scrollrt.h @@ -2,6 +2,12 @@ #ifndef __SCROLLRT_H__ #define __SCROLLRT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern bool sgbControllerActive; extern int light_table_index; extern BYTE *gpBufStart; @@ -33,4 +39,10 @@ void DrawAndBlit(); extern char *szMonModeAssert[18]; extern char *szPlrModeAssert[12]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SCROLLRT_H__ */ diff --git a/Source/setmaps.cpp b/Source/setmaps.cpp index 244e81325..ac9c371dd 100644 --- a/Source/setmaps.cpp +++ b/Source/setmaps.cpp @@ -172,7 +172,7 @@ void LoadSetMap() if (quests[Q_PWATER]._qactive == QUEST_INIT) quests[Q_PWATER]._qactive = QUEST_ACTIVE; LoadPreL3Dungeon("Levels\\L3Data\\Foulwatr.DUN", 19, 50); - LoadL3Dungeon("Levels\\L3Data\\Foulwatr.DUN", 31, 83); + LoadL3Dungeon("Levels\\L3Data\\Foulwatr.DUN", 20, 50); LoadPalette("Levels\\L3Data\\L3pfoul.pal"); InitPWaterTriggers(); break; diff --git a/Source/setmaps.h b/Source/setmaps.h index e5a3a0338..7df8c2230 100644 --- a/Source/setmaps.h +++ b/Source/setmaps.h @@ -2,6 +2,12 @@ #ifndef __SETMAPS_H__ #define __SETMAPS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + int ObjIndex(int x, int y); void AddSKingObjs(); void AddSChamObjs(); @@ -19,4 +25,10 @@ extern BYTE SkelChamTrans2[8]; extern BYTE SkelChamTrans3[36]; extern char *quest_level_names[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SETMAPS_H__ */ diff --git a/Source/sha.h b/Source/sha.h index e97f540dd..25be6a279 100644 --- a/Source/sha.h +++ b/Source/sha.h @@ -2,6 +2,12 @@ #ifndef __SHA_H__ #define __SHA_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + #define SHA1HashSize 20 //sha @@ -14,4 +20,10 @@ void SHA1ProcessMessageBlock(SHA1Context *context); void SHA1Reset(int n); void SHA1Init(SHA1Context *context); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SHA_H__ */ diff --git a/Source/sound.h b/Source/sound.h index 16618e920..2595023c1 100644 --- a/Source/sound.h +++ b/Source/sound.h @@ -2,6 +2,12 @@ #ifndef __SOUND_H__ #define __SOUND_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern SoundSample *DSBs[8]; extern BOOLEAN gbSndInited; extern HMODULE hDsound_dll; @@ -35,4 +41,10 @@ extern BOOLEAN gbSoundOn; extern BOOLEAN gbDupSounds; extern char unk_volume[4][2]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SOUND_H__ */ diff --git a/Source/spelldat.h b/Source/spelldat.h index 2c894f3b9..7edfa60a4 100644 --- a/Source/spelldat.h +++ b/Source/spelldat.h @@ -2,6 +2,18 @@ #ifndef __SPELLDAT_H__ #define __SPELLDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern SpellData spelldata[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SPELLDAT_H__ */ diff --git a/Source/spells.h b/Source/spells.h index 9eb299e4f..a59b87a67 100644 --- a/Source/spells.h +++ b/Source/spells.h @@ -2,6 +2,12 @@ #ifndef __SPELLS_H__ #define __SPELLS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + int GetManaAmount(int id, int sn); void UseMana(int id, int sn); BOOL CheckSpell(int id, int sn, char st, BOOL manaonly); @@ -9,4 +15,10 @@ void CastSpell(int id, int spl, int sx, int sy, int dx, int dy, int caster, int void DoResurrect(int pnum, int rid); void DoHealOther(int pnum, int rid); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SPELLS_H__ */ diff --git a/Source/stores.h b/Source/stores.h index 667158bfe..f3358b6f2 100644 --- a/Source/stores.h +++ b/Source/stores.h @@ -2,6 +2,12 @@ #ifndef __STORES_H__ #define __STORES_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int stextup; extern int storenumh; extern int stextlhold; @@ -136,5 +142,10 @@ void ReleaseStoreBtn(); /* rdata */ extern char *talkname[9]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __STORES_H__ */ diff --git a/Source/sync.h b/Source/sync.h index b65f9b194..f3d98d073 100644 --- a/Source/sync.h +++ b/Source/sync.h @@ -2,6 +2,12 @@ #ifndef __SYNC_H__ #define __SYNC_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern WORD sync_word_6AA708[MAXMONSTERS]; extern int sgnMonsters; extern WORD sgwLRU[MAXMONSTERS]; @@ -17,4 +23,10 @@ DWORD sync_update(int pnum, const BYTE *pbBuf); void sync_monster(int pnum, const TSyncMonster *p); void sync_init(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __SYNC_H__ */ diff --git a/Source/textdat.h b/Source/textdat.h index 2edb4f4ad..fff83b05e 100644 --- a/Source/textdat.h +++ b/Source/textdat.h @@ -2,7 +2,19 @@ #ifndef __TEXTDAT_H__ #define __TEXTDAT_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern const TextDataStruct alltext[]; extern const DWORD gdwAllTextEntries; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __TEXTDAT_H__ */ diff --git a/Source/themes.cpp b/Source/themes.cpp index bc808b6ca..ac2262f82 100644 --- a/Source/themes.cpp +++ b/Source/themes.cpp @@ -26,7 +26,7 @@ BOOL bCrossFlag; int ThemeGood[4] = { THEME_GOATSHRINE, THEME_SHRINE, THEME_SKELROOM, THEME_LIBRARY }; -int trm5x[25] = { +int trm5x[] = { -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, -2, -1, 0, 1, 2, @@ -34,7 +34,7 @@ int trm5x[25] = { -2, -1, 0, 1, 2 }; -int trm5y[25] = { +int trm5y[] = { -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, @@ -42,13 +42,13 @@ int trm5y[25] = { 2, 2, 2, 2, 2 }; -int trm3x[9] = { +int trm3x[] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 }; -int trm3y[9] = { +int trm3y[] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 diff --git a/Source/themes.h b/Source/themes.h index 35c4cb083..9a852ea1e 100644 --- a/Source/themes.h +++ b/Source/themes.h @@ -6,6 +6,12 @@ #ifndef __THEMES_H__ #define __THEMES_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern int numthemes; extern BOOL armorFlag; extern BOOL ThemeGoodIn[4]; @@ -63,4 +69,10 @@ extern int trm5y[25]; extern int trm3x[9]; extern int trm3y[9]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __THEMES_H__ */ diff --git a/Source/tmsg.h b/Source/tmsg.h index 7e23e31e5..d8d674d25 100644 --- a/Source/tmsg.h +++ b/Source/tmsg.h @@ -2,9 +2,21 @@ #ifndef __TMSG_H__ #define __TMSG_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + int tmsg_get(BYTE *pbMsg, DWORD dwMaxLen); void tmsg_add(BYTE *pbMsg, BYTE bLen); void tmsg_start(); void tmsg_cleanup(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __TMSG_H__ */ diff --git a/Source/town.h b/Source/town.h index b4025ec24..2f4bd952f 100644 --- a/Source/town.h +++ b/Source/town.h @@ -2,10 +2,22 @@ #ifndef __TOWN_H__ #define __TOWN_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void SetTownMicros(); void T_FillSector(BYTE *P3Tiles, BYTE *pSector, int xi, int yi, int w, int h); void T_FillTile(BYTE *P3Tiles, int xx, int yy, int t); void T_Pass3(); void CreateTown(int entry); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __TOWN_H__ */ diff --git a/Source/towners.cpp b/Source/towners.cpp index b291f5310..6f387112a 100644 --- a/Source/towners.cpp +++ b/Source/towners.cpp @@ -10,13 +10,13 @@ DWORD sgdwCowClicks; BOOL bannerflag; BOOL boyloadflag; BYTE *pCowCels; -TownerStruct towner[16]; +TownerStruct towner[NUM_TOWNERS]; #ifndef SPAWN const int snSFX[3][NUM_CLASSES] = { { PS_WARR52, PS_ROGUE52, PS_MAGE52 }, { PS_WARR49, PS_ROGUE49, PS_MAGE49 }, - { PS_WARR50, PS_ROGUE50, PS_MAGE50 } + { PS_WARR50, PS_ROGUE50, PS_MAGE50 }, }; #endif @@ -88,9 +88,9 @@ char AnimOrder[6][148] = { 1, 2, 1, 19, 18, 19, 1, 2, 1, 2, 3, -1 } }; -int TownCowX[3] = { 58, 56, 59 }; -int TownCowY[3] = { 16, 14, 20 }; -int TownCowDir[3] = { 1, 3, 4 }; +int TownCowX[] = { 58, 56, 59 }; +int TownCowY[] = { 16, 14, 20 }; +int TownCowDir[] = { DIR_SW, DIR_NW, DIR_N }; int cowoffx[8] = { -1, 0, -1, -1, -1, 0, -1, -1 }; int cowoffy[8] = { -1, -1, -1, 0, -1, -1, -1, 0 }; QuestTalkData Qtalklist[] = { @@ -180,7 +180,7 @@ void InitSmith() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_SMITH, 62, 63, 0, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_SMITH, 62, 63, 0, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\Smith\\SmithN.CEL", NULL); for (i = 0; i < 8; i++) { @@ -197,7 +197,7 @@ void InitBarOwner() int i; bannerflag = FALSE; // unused - InitTownerInfo(numtowners, 96, 1, TOWN_TAVERN, 55, 62, 3, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_TAVERN, 55, 62, 3, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\TwnF\\TwnFN.CEL", NULL); for (i = 0; i < 8; i++) { @@ -213,7 +213,7 @@ void InitTownDead() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_DEADGUY, 24, 32, -1, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_DEADGUY, 24, 32, -1, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\Butch\\Deadguy.CEL", NULL); for (i = 0; i < 8; i++) { @@ -229,7 +229,7 @@ void InitWitch() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_WITCH, 80, 20, 5, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_WITCH, 80, 20, 5, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\TownWmn1\\Witch.CEL", NULL); for (i = 0; i < 8; i++) { @@ -245,7 +245,7 @@ void InitBarmaid() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_BMAID, 43, 66, -1, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_BMAID, 43, 66, -1, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\TownWmn1\\WmnN.CEL", NULL); for (i = 0; i < 8; i++) { @@ -262,7 +262,7 @@ void InitBoy() int i; boyloadflag = TRUE; - InitTownerInfo(numtowners, 96, 1, TOWN_PEGBOY, 11, 53, -1, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_PEGBOY, 11, 53, -1, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\TownBoy\\PegKid1.CEL", NULL); for (i = 0; i < 8; i++) { @@ -278,7 +278,7 @@ void InitHealer() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_HEALER, 55, 79, 1, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_HEALER, 55, 79, 1, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\Healer\\Healer.CEL", NULL); for (i = 0; i < 8; i++) { @@ -294,7 +294,7 @@ void InitTeller() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_STORY, 62, 71, 2, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_STORY, 62, 71, 2, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\Strytell\\Strytell.CEL", NULL); for (i = 0; i < 8; i++) { @@ -310,7 +310,7 @@ void InitDrunk() { int i; - InitTownerInfo(numtowners, 96, 1, TOWN_DRUNK, 71, 84, 4, 10); + InitTownerInfo(numtowners, 96, TRUE, TOWN_DRUNK, 71, 84, 4, 10); InitQstSnds(numtowners); towner[numtowners]._tNData = LoadFileInMem("Towners\\Drunk\\TwnDrunk.CEL", NULL); for (i = 0; i < 8; i++) { @@ -334,22 +334,22 @@ void InitCows() x = TownCowX[i]; y = TownCowY[i]; dir = TownCowDir[i]; - InitTownerInfo(numtowners, 128, 0, TOWN_COW, TownCowX[i], TownCowY[i], -1, 10); + InitTownerInfo(numtowners, 128, FALSE, TOWN_COW, x, y, -1, 10); towner[numtowners]._tNData = pCowCels; SetTownerGPtrs(towner[numtowners]._tNData, towner[numtowners]._tNAnim); towner[numtowners]._tNFrames = 12; NewTownerAnim(numtowners, towner[numtowners]._tNAnim[dir], towner[numtowners]._tNFrames, 3); towner[numtowners]._tAnimFrame = random_(0, 11) + 1; - towner[numtowners]._tSelFlag = 1; + towner[numtowners]._tSelFlag = TRUE; strcpy(towner[numtowners]._tName, "Cow"); xo = x + cowoffx[dir]; yo = y + cowoffy[dir]; - if (!dMonster[x][yo]) + if (dMonster[x][yo] == 0) dMonster[x][yo] = -(numtowners + 1); - if (!dMonster[xo][y]) + if (dMonster[xo][y] == 0) dMonster[xo][y] = -(numtowners + 1); - if (!dMonster[xo][yo]) + if (dMonster[xo][yo] == 0) dMonster[xo][yo] = -(numtowners + 1); numtowners++; @@ -362,7 +362,7 @@ void InitTowners() boyloadflag = FALSE; InitSmith(); InitHealer(); - if (quests[Q_BUTCHER]._qactive && quests[Q_BUTCHER]._qactive != QUEST_DONE) + if (quests[Q_BUTCHER]._qactive != QUEST_NOTAVAIL && quests[Q_BUTCHER]._qactive != QUEST_DONE) InitTownDead(); InitBarOwner(); InitTeller(); @@ -377,7 +377,7 @@ void FreeTownerGFX() { int i; - for (i = 0; i < 16; i++) { + for (i = 0; i < NUM_TOWNERS; i++) { if (towner[i]._tNData == pCowCels) { towner[i]._tNData = NULL; } else if (towner[i]._tNData) { @@ -393,7 +393,7 @@ void TownCtrlMsg(int i) int p; int dx, dy; - if (towner[i]._tbtcnt) { + if (towner[i]._tbtcnt != 0) { p = towner[i]._tVar1; dx = abs(towner[i]._tx - plr[p]._px); dy = abs(towner[i]._ty - plr[p]._py); @@ -502,7 +502,7 @@ void ProcessTowners() { int i, ao; - for (i = 0; i < 16; i++) { + for (i = 0; i < NUM_TOWNERS; i++) { switch (towner[i]._ttype) { case TOWN_SMITH: TownBlackSmith(); @@ -770,13 +770,13 @@ void TalkToTowner(int p, int t) RemoveInvItem(p, i); quests[Q_MUSHROOM]._qactive = QUEST_ACTIVE; quests[Q_MUSHROOM]._qlog = TRUE; - quests[Q_MUSHROOM]._qvar1 = 2; + quests[Q_MUSHROOM]._qvar1 = QS_TOMEGIVEN; towner[t]._tbtcnt = 150; towner[t]._tVar1 = p; InitQTextMsg(TEXT_MUSH8); towner[t]._tMsgSaid = TRUE; } else if (quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE) { - if (quests[Q_MUSHROOM]._qvar1 >= 2 && quests[Q_MUSHROOM]._qvar1 <= 4) { + if (quests[Q_MUSHROOM]._qvar1 >= QS_TOMEGIVEN && quests[Q_MUSHROOM]._qvar1 <= QS_MUSHPICKED) { if (PlrHasItem(p, IDI_MUSHROOM, &i) != NULL) { RemoveInvItem(p, i); quests[Q_MUSHROOM]._qvar1 = 5; @@ -857,7 +857,7 @@ void TalkToTowner(int p, int t) RemoveInvItem(p, i); SpawnQuestItem(IDI_SPECELIX, towner[t]._tx, towner[t]._ty + 1, 0, 0); InitQTextMsg(TEXT_MUSH4); - quests[Q_MUSHROOM]._qvar1 = 7; + quests[Q_MUSHROOM]._qvar1 = QS_BRAINGIVEN; Qtalklist[TOWN_HEALER]._qblkm = -1; } } diff --git a/Source/towners.h b/Source/towners.h index c02191c25..a574c3fb1 100644 --- a/Source/towners.h +++ b/Source/towners.h @@ -2,7 +2,13 @@ #ifndef __TOWNERS_H__ #define __TOWNERS_H__ -extern TownerStruct towner[16]; +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + +extern TownerStruct towner[NUM_TOWNERS]; int GetActiveTowner(int t); void SetTownerGPtrs(BYTE *pData, BYTE **pAnim); @@ -41,5 +47,10 @@ void CowSFX(int pnum); /* data */ extern QuestTalkData Qtalklist[]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE #endif /* __TOWNERS_H__ */ diff --git a/Source/track.cpp b/Source/track.cpp index 5c582b364..9879f0800 100644 --- a/Source/track.cpp +++ b/Source/track.cpp @@ -35,7 +35,7 @@ void track_repeat_walk(BOOL rep) sgbIsWalking = rep; if (rep) { - sgbIsScrolling = 0; + sgbIsScrolling = FALSE; sgdwLastWalk = SDL_GetTicks() - 50; NetSendCmdLoc(TRUE, CMD_WALKXY, cursmx, cursmy); } else if (sgbIsScrolling) { diff --git a/Source/track.h b/Source/track.h index a2a2506c9..99c42082a 100644 --- a/Source/track.h +++ b/Source/track.h @@ -2,8 +2,20 @@ #ifndef __TRACK_H__ #define __TRACK_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void track_process(); void track_repeat_walk(BOOL rep); BOOL track_isscrolling(); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __TRACK_H__ */ diff --git a/Source/trigs.cpp b/Source/trigs.cpp index 683c86f9e..fb5f14fd1 100644 --- a/Source/trigs.cpp +++ b/Source/trigs.cpp @@ -35,30 +35,34 @@ void InitTownTriggers() { int i; - trigs[0]._tx = 25; - trigs[0]._ty = 29; - trigs[0]._tmsg = WM_DIABNEXTLVL; + numtrigs = 0; + + trigs[numtrigs]._tx = 25; + trigs[numtrigs]._ty = 29; + trigs[numtrigs]._tmsg = WM_DIABNEXTLVL; + numtrigs++; - numtrigs = 1; #ifndef SPAWN if (gbMaxPlayers == MAX_PLRS) { for (i = 0; i < sizeof(townwarps) / sizeof(townwarps[0]); i++) { townwarps[i] = TRUE; } - trigs[1]._tx = 49; - trigs[1]._ty = 21; - trigs[1]._tmsg = WM_DIABTOWNWARP; - trigs[1]._tlvl = 5; - trigs[2]._tx = 17; - trigs[2]._ty = 69; - trigs[2]._tmsg = WM_DIABTOWNWARP; - trigs[2]._tlvl = 9; - trigs[3]._tx = 41; - trigs[3]._ty = 80; - trigs[3]._tmsg = WM_DIABTOWNWARP; - trigs[3]._tlvl = 13; - numtrigs = 4; + trigs[numtrigs]._tx = 49; + trigs[numtrigs]._ty = 21; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 5; + numtrigs++; + trigs[numtrigs]._tx = 17; + trigs[numtrigs]._ty = 69; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 9; + numtrigs++; + trigs[numtrigs]._tx = 41; + trigs[numtrigs]._ty = 80; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 13; + numtrigs++; } else { #endif for (i = 0; i < MAX_PLRS - 1; i++) { @@ -66,11 +70,11 @@ void InitTownTriggers() } #ifndef SPAWN if (plr[myplr].pTownWarps & 1) { - trigs[1]._tx = 49; - trigs[1]._ty = 21; - trigs[1]._tmsg = WM_DIABTOWNWARP; - trigs[1]._tlvl = 5; - numtrigs = 2; + trigs[numtrigs]._tx = 49; + trigs[numtrigs]._ty = 21; + trigs[numtrigs]._tmsg = WM_DIABTOWNWARP; + trigs[numtrigs]._tlvl = 5; + numtrigs++; townwarps[0] = TRUE; } if (plr[myplr].pTownWarps & 2) { diff --git a/Source/trigs.h b/Source/trigs.h index fe7243bbd..2bad3b8c4 100644 --- a/Source/trigs.h +++ b/Source/trigs.h @@ -2,6 +2,12 @@ #ifndef __TRIGS_H__ #define __TRIGS_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + extern BOOL townwarps[3]; extern BOOL trigflag; extern int numtrigs; @@ -47,4 +53,10 @@ extern int L4DownList[6]; extern int L4TWarpUpList[4]; extern int L4PentaList[33]; +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __TRIGS_H__ */ diff --git a/Source/wave.h b/Source/wave.h index 1830b95b0..e77a2538a 100644 --- a/Source/wave.h +++ b/Source/wave.h @@ -2,6 +2,12 @@ #ifndef __WAVE_H__ #define __WAVE_H__ +DEVILUTION_BEGIN_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + void WCloseFile(HANDLE file); LONG WGetFileSize(HANDLE hsFile, DWORD *lpFileSizeHigh, const char *FileName); void WGetFileArchive(HANDLE hsFile, DWORD *retry, const char *FileName); @@ -9,4 +15,10 @@ BOOL WOpenFile(const char *FileName, HANDLE *phsFile, BOOL mayNotExist); void WReadFile(HANDLE hsFile, LPVOID buf, DWORD to_read, const char *FileName); int WSetFilePointer(HANDLE file1, int offset, HANDLE file2, int whence); +#ifdef __cplusplus +} +#endif + +DEVILUTION_END_NAMESPACE + #endif /* __WAVE_H__ */ diff --git a/SourceX/DiabloUI/credits.cpp b/SourceX/DiabloUI/credits.cpp index 988b01a91..af0d990de 100644 --- a/SourceX/DiabloUI/credits.cpp +++ b/SourceX/DiabloUI/credits.cpp @@ -204,9 +204,9 @@ private: void CreditsRenderer::Render() { const int offset_y = -VIEWPORT.h + (SDL_GetTicks() - ticks_begin_) / 40; - if (offset_y == prev_offset_y_) + /*if (offset_y == prev_offset_y_) return; - prev_offset_y_ = offset_y; + prev_offset_y_ = offset_y;*/ DrawArt(0, 0, &ArtBackground); if (font == nullptr) @@ -215,11 +215,11 @@ void CreditsRenderer::Render() const std::size_t lines_begin = std::max(offset_y / LINE_H, 0); const std::size_t lines_end = std::min(lines_begin + MAX_VISIBLE_LINES, CREDITS_LINES_SIZE); - if (lines_begin >= lines_end) { + /*if (lines_begin >= lines_end) { if (lines_end == CREDITS_LINES_SIZE) finished_ = true; return; - } + }*/ while (!lines_.empty() && lines_.front().index != lines_begin) lines_.pop_front(); @@ -243,9 +243,9 @@ void CreditsRenderer::Render() if (line.palette_version != pal_surface_palette_version) line = PrepareLine(line.index); - decltype(SDL_Rect().x) dest_x = VIEWPORT.x + 31; + decltype(SDL_Rect().x) dest_x = VIEWPORT.x + 16/*31*/; if (CREDITS_LINES[line.index][0] == '\t') - dest_x += 40; + dest_x += 16/*40*/; SDL_Rect dst_rect = { dest_x, dest_y, 0, 0 }; ScaleOutputRect(&dst_rect); @@ -255,6 +255,9 @@ void CreditsRenderer::Render() ErrSdl(); } SDL_SetClipRect(GetOutputSurface(), nullptr); + + if(lines_end==CREDITS_LINES_SIZE) finished_ = true; + } } // namespace diff --git a/SourceX/DiabloUI/credits_lines.cpp b/SourceX/DiabloUI/credits_lines.cpp index 1392ed4df..c72f82999 100644 --- a/SourceX/DiabloUI/credits_lines.cpp +++ b/SourceX/DiabloUI/credits_lines.cpp @@ -3,461 +3,472 @@ namespace dvl { const char *const CREDITS_LINES[] = { - "Game Design", - " Blizzard North", + "GAME DESIGN", + " BLIZZARD NORTH", "", - "Senior Designers", - " Erich Schaefer, David Brevik", + "SENIOR DESIGNERS", + " ERICH SCHAEFER, DAVID BREVIK", "", - "Additional Design", - " Max Schaefer, Eric Sexton, Kenneth Williams", + "ADDITIONAL DESIGN", + " MAX SCHAEFER, ERIC SEXTON, KENNETH WILLIAMS", "", - "Lead Programmer", - " David Brevik", + "LEAD PROGRAMMER", + " DAVID BREVIK", "", - "Senior Programmers", - " Richard Seis, Doron Gartner,", - " Patrick Wyatt, Mike O'Brien", + "SENIOR PROGRAMMERS", + " RICHARD SEIS, DORON GARTNER,", + " PATRICK WYATT, MIKE O'BRIEN", "", - "Programming", - " Peter Brevik, Robin van der Wel, Jon Morin", + "PROGRAMMING", + " PETER BREVIK, ROBIN VAN DER WEL, JON MORIN", "", - "Special Guest Programmers", - " Collin Murray, Frank Pearce", + "SPECIAL GUEST PROGRAMMERS", + " COLLIN MURRAY, FRANK PEARCE", "", - "Battle.net Programming", - " Mike O'Brien, Mike Morhaime, Dan Liebgold", + "BATTLE.NET PROGRAMMING", + " MIKE O'BRIEN, MIKE MORHAIME, DAN LIEBGOLD", "", - "Serial Communications Programming", - " Jeff Strain, Mike O'Brien", + "SERIAL COMMUNICATIONS PROGRAMMING", + " JEFF STRAIN, MIKE O'BRIEN", "", - "Installer Programming", - " Bob Fitch, Patrick Wyatt", + "INSTALLER PROGRAMMING", + " BOB FITCH, PATRICK WYATT", "", - "Art Directors", - " Erich Schaefer, Samwise Didier", + "ART DIRECTORS", + " ERICH SCHAEFER, SAMWISE DIDIER", "", - "Artwork", - " Michio Okamura, Eric Sexton, Ben Haas, Patrick Tougas,", - " Kelly Johnson, Erich Schaefer, Max Schaefer, Hugh Tom", - " Byrne, Roman Kenney, Samwise Didier, Dave Berggren,", - " Micky Neilson, Eric Flannum, Justin Thavirat, Brian", - " Sousa, Stu Rose, Nick Carpenter, Joeyray Hall", + "ARTWORK", + " MICHIO OKAMURA, ERIC SEXTON, BEN HAAS, PATRICK TOUGAS,", + " KELLY JOHNSON, ERICH SCHAEFER, MAX SCHAEFER, HUGH TOM", + " BYRNE, ROMAN KENNEY, SAMWISE DIDIER, DAVE BERGGREN,", + " MICKY NEILSON, ERIC FLANNUM, JUSTIN THAVIRAT, BRIAN", + " SOUSA, STU ROSE, NICK CARPENTER, JOEYRAY HALL", "", - "Technical Artwork", - " Christopher Root, Mark Sutherland,", - " Robert Djordjevich, Jeffrey Vaughn", + "TECHNICAL ARTWORK", + " CHRISTOPHER ROOT, MARK SUTHERLAND,", + " ROBERT DJORDJEVICH, JEFFREY VAUGHN", "", - "Cinematic Art Directors", - " Duane Stinnett, Matt Samia", + "CINEMATIC ART DIRECTORS", + " DUANE STINNETT, MATT SAMIA", "", - "3D Cinematic Artwork", - " Duane Stinnett, Matt Samia, Rob McNaughton,", - " Eric Flannum, Dave Pursley, Micky Neilson,", - " Maxx Marshall, Trevor Jacobs, Brian Sousa,", - " Samwise Didier, Ron Smorynski, Ben Haas, Patrick Tougas", + "3D CINEMATIC ARTWORK", + " DUANE STINNETT, MATT SAMIA, ROB MCNAUGHTON,", + " ERIC FLANNUM, DAVE PURSLEY, MICKY NEILSON,", + " MAXX MARSHALL, TREVOR JACOBS, BRIAN SOUSA,", + " SAMWISE DIDIER, RON SMORYNSKI, BEN HAAS, PATRICK TOUGAS", "", - "Cinematic Technical Artwork", - " Joeyray Hall ", + "CINEMATIC TECHNICAL ARTWORK", + " JOEYRAY HALL ", "", - "Executive Producer", - " Allen Adham", + "EXECUTIVE PRODUCER", + " ALLEN ADHAM", "", - "Producer", - " Bill Roper", + "PRODUCER", + " BILL ROPER", "", - "Associate Producer", - " James Phinney", + "ASSOCIATE PRODUCER", + " JAMES PHINNEY", "", - "Diablo Strike Team", - " Allen Adham, Ron Millar, Mike O'Brien,", - " James Phinney, Bill Roper, Patrick Wyatt", + "DIABLO STRIKE TEAM", + " ALLEN ADHAM, RON MILLAR, MIKE O'BRIEN,", + " JAMES PHINNEY, BILL ROPER, PATRICK WYATT", "", - "Music", - " Matt Uelmen", + "MUSIC", + " MATT UELMEN", "", - "Sound Design", - " Matt Uelmen, Glenn Stafford", + "SOUND DESIGN", + " MATT UELMEN, GLENN STAFFORD", "", - "Cinematic Music & Sound", - " Glenn Stafford, Matt Uelmen", + "CINEMATIC MUSIC & SOUND", + " GLENN STAFFORD, MATT UELMEN", "", - "Voice Production, Direction & Casting", - " Mark Schwarz, Glenn Stafford, Bill Roper", + "VOICE PRODUCTION, DIRECTION & CASTING", + " MARK SCHWARZ, GLENN STAFFORD, BILL ROPER", "", - "Script & Story", - " Erich Schaefer, Eric Sexton,", - " Chris Metzen, Bill Roper", + "SCRIPT & STORY", + " ERICH SCHAEFER, ERIC SEXTON,", + " CHRIS METZEN, BILL ROPER", "", - "Voice Editing", - " Glenn Stafford", + "VOICE EDITING", + " GLENN STAFFORD", "", - "Voices", - " Michael Haley, Glynnis Talken, Michael Gough,", - " Paul Eiding, Lani Minella, Steve Brodie, Bill Roper,", - " Mark Schwarz, Glenn Stafford, Chris Metzen, Max Schaefer", + "VOICES", + " MICHAEL HALEY, GLYNNIS TALKEN, MICHAEL GOUGH,", + " PAUL EIDING, LANI MINELLA, STEVE BRODIE, BILL ROPER,", + " MARK SCHWARZ, GLENN STAFFORD, CHRIS METZEN, MAX SCHAEFER", "", - "Recording Engineer", - " Robert Koenigsberg", - "", - "Manual Design & Layout", - " Peter Underwood, Jeffrey Vaughn,", - " Chris Metzen, Bill Roper", - "", - "Manual Artwork", - " Samwise Didier, Chris Metzen,", - " Roman Kenney, Maxx Marshall", - "", - "Provisional Director of QA (Lead Tester)", - " Shane Dabiri", - "", - "QA Assault Team (Testers)", - " Christopher Cross, Mike Givens, Dave Hale,", - " Brian \"Doc\" Love, Hung Nguyen, Dean Shipley,", - " Chris Sigaty, Ian Welke, Jamie Wiggs", - "", - "QA Special Ops Team (Compatibility Testers)", - " Adam Maxwell, Russell \"Rug\" Miller", - "", - "QA Artillery Support (Additional Testers) ", - " Rich Alcazar, Mike Jones, Rev. Dan Moore, Matt Morris,", - " Mark Pfeiffer, Harish \"Pepe the Enforcer\" Rao, Chris Millar", - "", - "QA Counterintelligence", - " Alan Dabiri, Jesse McReynolds, Walter Takata", - "", - "Order of Network Information Services", - " Robert Bridenbecker, Jason \"Brother Shaggy\" Schmit,", - " Jamie \"Brother Gug\" Steigerwald, Richard Seis ", - "", - "Customer Support", - " John Schwartz, Vic Larson, Chad Chaudry, Mick Yanko,", - " Brandon Riseling, Kirk Mahony, Tony Hardy, Richard", - " Amtower, Collin Smith, Andrew Edwards, Roger Eberhart", - "", - "Sales", - " Jorge Rivero, Rob Beatie", - "", - "Dunsel", - " Alan Dabiri", - "", - "Mr. Dabiri's Background Vocalists", - " Karin Colenzo, Christina Cade,", - " Kim Farrington, Melissa Edwards", - "", - "Public Relations", - " Linda Duttenhaver, Susan Wooley", - "", - "Marketing", - " John Patrick, Steve Huot, Neal Hubbard, Kathy Carter", - "", - "International Sales", - " Ralph Becker, Chris Yoshimura", - "", - "U.S. Sales", - " Todd Coyle, Danny Kearns", - "", - "Manufacturing", - " John Goodman, Tom Bryan", - "", - "Legal & Business", - " Paula Duffy, Eric Roeder, Paul Sams, Kenneth Williams", - "", - "Special Thanks To", - " Primenet, Earthlink, AOL, Compuserve, ATI, Matrox, STB, ", - " Creative Labs, Logitech, U.S. Robotics, Gravis, Cyrix", - "", - "Thanks To", - " Ian Colquhoun, Rod Shean, Brian Fitzgerald, Sharon Schafer, Todd ", - " Schafer, Richard and Sandra Schaefer, Rick Bowles, Greg Bogden, ", - " Cindy Sievert, Brad Mason, Chuck Goldman, Karin Colenzo, Wendy ", - " Brevik, Jennie Brevik, Hanna Carroll, Katie Newell, Karen Weiss, ", - " Kurt Beaver, Stan McDonald, Brian Sexton, Michael Wan, Megan ", - " Williams, Jessica Gensley, Beth Ann Parks, Brian Piltin, Johnathan ", - " Root, Brett Supernaw, Sabeer Bhatia, Mark Rearick, Brad Mason, ", - " Diane Kodama, Bernadette Sexton, Barbara Uhlmann, Patricia", - " McDonald, Kris Kelley, Alissa Vaage, Denise Hernandez, Paula ", - " White, Rachel Marie Hawley, Laura Gaber, Isaac Matarasso,", - " Susan Stafford, Gretchen Witte, Jason Sailor, Eufemia Palomino, ", - " Nathalie Didier, Nicole Welke, Dawn Caddel, Anna-Marcelle ", - " Okamura, Amber Okamura, Megan Okamura Tracey McNaughton, ", - " Trisha Ann Ochoa, Annie Strain, Dr. Gregory T. Street, Ray the Soda ", - " Guy, Sam Raimi, A. Guinness Brewing Co., John Woo, Chow Yun Fat, ", - " Jackie Chan,Proposition 215, Rumiko Takahashi, Bunchy & Mason, ", - " The Friends of Stan, The Zoo Crew, Team Hamro, Brazil 2001, RUSH, ", - " Cornholio, THE BROS., Dar, Emeril Lagasse, Tom Waits, Ice-Cube, ", - " The Strike Team Deflectors, Tony Levin, Big Jim and the Twins, ", - " Jag`rmeister, The Megasphere, Condor, The Allower, The Sunday ", - " Night Group, Gravitar, Steinway Pianos, Round Table Pizza, The Poxy ", - " Boggards, Urban Mystic & Co., Caffeine, Hunter Rose, Marly ", - " mediums in the box, sweet Poteen, Dave Scarpitti, TheByter, Bim ", - " Man, Krissann for color, Patty at Avalon Tattoo, James, Whaleboy, ", - " Dunsel Training Institute, monkeys, Dob Bole, Rootes Group, Porshe, ", - " Bongo, Scarlett, Apollo, The House of Mediocrity, Amelias, The King, ", - " Saag and all the folks at Davidson", - "", - "In memory of", - " Lawrence and Barbara Williams", - " David A. Hargrave", - " Tony \"Xatre\" Collin", - " Thomas H Sexton", - "", - "Very Special Thanks to", - " Bob and Jan Davidson", - " Walter Forbes", - "", - "The Ring of One Thousand", - " Andrew Abernathy, Christopher Abramo, David Adams, David ", - " Adcox, Marko Agterberg, Cory Aiken, Judah Altaras, John ", - " Alvarez, Jose Alvarez, Richard Amable, Alexander Amaral, ", - " Scott Amis, Vincent Amoroso, Mark An, David Andersen, Jason ", - " Andrew Abernathy, Christopher Abramo, David Adams, David ", - " Adcox, Marko Agterberg, Cory Aiken, Judah Altaras, John ", - " Alvarez, Jose Alvarez, Richard Amable, Alexander Amaral, ", - " Scott Amis, Vincent Amoroso, Mark An, David Andersen, Jason ", - " Andersen, Aaron Anderson, George Anderson, Matthew ", - " Anderson, Michael Anderson, Sean Anderson, Robert Andrade, ", - " Cerny Andre, Michael Andreev, Devin Angle, Brian Apple, ", - " Brian Arbuthnot, Billy Arden, Dorian Arnold, Andre Arsenault, ", - " Erik Asplund, Mark Assam, John Athey, Jason Attard, Jeff ", - " Atwood, Ricky Au, Scott Avery, Rand Babcock, Steve Babel, ", - " Raymond Bacalso, Ed Bachta, Steven Back, Scott Baeder, Alex ", - " Baevski, Scott Bailey, Kenneth Baird, Thomas Baker, Todd ", - " Bala, Jan Ball, Greg Baltz, Blake Baltzley, Doug Bambrick, Wes ", - " Bangerter, Paul Barfuss, Chris Barghout, Dave Barnebey, Jon ", - " Barnhart, Terje Barth, Nicole Baskin, Bernard Baylen, Ryan ", - " Bear, Phil Bedard, Todd Belcher, Chip Bell, Erez Ben-Aharon, ", - " Jonathan Bender, Nick Bennett, Ireney Berezniak, Ted Berg, ", - " Gunnar Bergem, Russell Beuker, Ed Bickford, Stephen Biles, ", - " John Billdt, Gerald Binder, John Bird, Hannah Blackerby, Tom ", - " Blackerby, Clayton Blackwell, Thomas Blake, Shawn Blaszak, ", - " Daniel Bliss, Fred Bliss, Jeff Bliss, Jon Blum, Rune Boersjoe, ", - " Andrew Boggs, Dave Boisvenu, Joe Bolt, John Bonds, Jeff ", - " Borenstein, Dorian Borin, Ed Boris, Bartholomew Botta, ", - " Michael Boutin, Michael Boyd, Charles Boyer, Mike ", - " Boyersmith, Michael Boyko, Eric Bradberry, John Brandstetter, ", - " Ryan Breding, Paul Brinkmann, Patrick Briscoe, Scott Brisko, ", - " Jeremy Britton, Adrian Broadhead, Glenn Brouwer, Joe Brown, ", - " Sébastien Brulotte, Darrell Brunsch, William Bryan, Jason ", - " Bucher, Chris Buchinger, Clayton Buckingham, John Buckles, ", - " David Bugay, Ed Bujone, Erik Burgess, Gabriel Burkett, Chris ", - " Burnes, Richard Butler, Jeffrey Bye, Dougall Campbell, Donnie ", - " Cannon, Shane Cantrell, Connor Caple, Daniel Carey, James ", - " Carlton, Michael Carmel, Mike Carpenter, Ronald Carruthers, ", - " Phil Carter, Bryce Cartmill, Eric Cartwright, Anthony Caruso, ", - " Lon Casey, Tim Caster, Aaron Chan, Otto Chan, Gene Chang, ", - " Hsiao-Lung Chang, William Chang, George Chappel, Larry ", - " Charbonneau, Troy Chase, Bruce Chen, Chun Hsien Chen, Sam ", - " Chen, Tzu-Mainn Chen, Mike Cheng, Chris Chiapusio, Damien ", - " Chiesa, Nick Chin, Nim Ching, Jonathan Chinn, Michael Chinn, ", - " Philander Chiu, Thayne Christiansen, Philip Chui, Steve ", - " Cintamani, Richard Ciordia, Colin Clark, Steve Clark, Samuel ", - " Clements, Meredith Clifton, Jeff Cohen, Dale Colton, Dax ", - " Combe, Matt Compton, Jacob Conklin, Richard Conn, Zac ", - " Cook, Tim Coolong, Gregory Coomer, Dennis Cosgrove, Kelly ", - " Couch, Andrew Coulter, Eric Coutinho, David Coutts, James ", - " Craig, John Craig, Kazial Craig, John Crawford, Marcelo ", - " Crespo, Orville Crews, Tim Cristy, Elmer Crosby III, Russell ", - " Cullison, Ryan Cupples, Andrew Dagley, Steve Dallaire, Richard ", - " Dalton, David Dandar, Pro Daulo, Rob Dautermann, Mike ", - " Davies, Kalieb Davis, Marshall Davis, Ronald Davis, Danny De ", - " Bie, Marc De Filippis, Myles Deighton, Kent Dejarnett, Anthony ", - " Delarosa, Neil Dempster, Peter Denitto, Joaquim Dentz, Scott ", - " Dewar, Anish Dhingra, Philip Dhingra, David Diaz, Stewart ", - " Dicks, Brad Dietz, Josh Dietz, Colleen Diggins, Mike Ditchburn, ", - " Eric Dittman, Allen Do, Huy Doan, Matthew Dolman, Antoine ", - " Dongois, Eamonn Donohoe, Bill Dorell, Mark Dorison, Dan ", - " Dorsett, Chris Dorsey, Jim Dosé, Willis Doss, Chin Du, William ", - " Dubis, Timothy Duewell, Brandon Dunn, Andrew Durham, Don ", - " Duvall, Kevin Dvojack, Daniel Eaton, Paul Eberting, Eric ", - " Echelbarger, Lance Eddleman, Ben Eggers, David Eggum, John ", - " Ehde, Brian Eikenberry, Patrick Elven, Peter Engdahl, Philip ", - " Engdahl, Michael Ennis, Darren Eslinger, Eric Ezell, Darren ", - " Falslev, Stephen Feather, Tony Fenn, Ben Ferguson, Mike ", - " Fernandez, Gwendal Feuillet, Guy Fietz, Julian Figueroa, Dale ", - " Fillpot, Stan Finchem, Michael Finley, Nick Fisher, William ", - " Fisher, Mark Fitlin, Dave Flatt, Joel J. Flores, John Folkers, ", - " Steven Forgie, Tom Forsythe, Matthew Foster, Scott Francis, ", - " Jim Frank, Paulo Fraser, Glenn French, Kurt Frerichs, Chris ", - " Frey, Mark Friedman, Charles Friedmann, Dan Friend, Kirk ", - " Fry, Aaron Fu, Erik Gaalema, Brandon Gabbard, Phil Gagner, ", - " Tommy Gannon, David Gappmayer, Chris Garrison, Tony ", - " Garrison, David Gasca, Jeremy Gasser, Michael Geist, Michael ", - " Genereux, Daniel Genovese, Josh Gerwin, Paul Gibson, William ", - " Gilchrist, Gabriel Gils Carbo, Chad Glendenin, Ryan Glinski, ", - " Dean Gobrecht, Andrew Goldfinch, David Goodman, Mark ", - " Goodson, Matt Gordon, Frank Gorgenyi, Sean Gould, Perry ", - " Goutsos, Ed Govednik, Michael Grayson, Chris Green, Justin ", - " Grenier, Jeff Greulich, Don Grey, Rob Griesbeck, Don Griffes, ", - " Kimberly Griffeth, Jay Grizzard, Don Gronlund, Joe Gross, ", - " Troy Growden, Greg Guilford, David Gusovsky, Jeremy ", - " Guthrie, Adam Gutierrez, James Guzicki, Matthew Haas, Matt ", - " Hadley, Ryan Hagelstrom, Bobby Hagen, Ben Hall, Brian Hall, ", - " Kris Hall, Calvin Hamilton, Kris Hamilton, Bo Hammil, Dave ", - " Hans, Rick Hansen, Robert Harlan, Travis Harlan, Seth ", - " Harman, Jeff Harris, Shawn Hartford, Adam Hartsell, Neil ", - " Harvey, Ray Hayes, John Hein, Chris Heinonen, Christer ", - " Helsing, Chris Hempel, Dustin Hempel, Mathieu Henaire, Matt ", - " Henry, Chuck Herb, Michael Herron, Sage Herron, Thomas ", - " Herschbach, Cliff Hicks, Nelson Hicks, Paul Hierling, William ", - " Hiers, Mike Higdon, Tim Hildebrand, Casey Hinkle, Ryan ", - " Hitchings, Wes Hix, Alan Ho, Jenson Ho, Alan Hoffman, Jeff ", - " Hoffman, Eleanor Hoffmann, Steve Hogg, Richard Holler, Brian ", - " Homolya, Wade Hone, Joe Horvath, Jeff Howe, Eric Hudson, ", - " Glen Huey, Chris Hufnagel, Joshua Hughes, Melissa Hughes, ", - " Arief Hujaya, Thomas Hulen, Ryan Hupp, Justin Hurst, Rick ", - " Hutchins, Steve Iams, Mike Iarossi, Bjorn Idren, Johan Idrén, ", - " Micah Imparato, Joe Ingersoll, David Ingram, Greg Ipp, Rodney ", - " Irvin, Darin Isola, Justin Itoh, Mario Ivan, Fredrik Ivarsson, ", - " Dax Jacobson, Michael Jacques, Stevens Jacques, Duane Jahnke, ", - " William Jambrosek, Daniel Janick, Narciso Jaramillo, Neil ", - " Jariwala, Harvie Jarriell, Scott Javadi, Joe Jenkins, Bart ", - " Jennings, Paul Jennings, Julien Jenny, Jason Jensen, Martin ", - " Jeremy, Mark Jeschke, Andy Johnson, James Johnson, Leigh ", - " Johnson, Mark Johnson, Rupert Johnson, Clyde Jones, Michael ", - " Jones, Tim Jordan, Ben Judy, Michael Kaae, Steve Kaczkowski, ", - " Neville Kadwa, Brian Kaisner, Yoshihisa Kameyama, Michael ", - " Kanemura, Daniel Kao, Eric Karabin, Ben Katz, Christopher ", - " Kawamura, Erick Kayser, Craig Keddie, Kevin Kelley, Bryan ", - " Kemp, Michael Kendrigan, Dan Kerber, Timothy Kerber, Tomi ", - " Keski-Heikkilä, Greg Kettering, Nathan Kilber, Howard Kim, ", - " Orrin Kinion, Jon Kirst, David Kitch, John Klingbeil, Neil ", - " Klopfenstein, Kerry Knouse, David Knox, Said Kobeissi, Jeff ", - " Koches, Hades Kong, Jeff Kong, Kevin Konkle, Steve Koon, ", - " David Koontz, Dan Koopmann, Steve Koskela, Kuan Kou, ", - " Cameron Kracke, Jensen Krage, York Kramer, Cedar Kraus, ", - " Jason Kraus, Bobby Krimen, Melissa Krispli, Steven Krispli, ", - " James Kruger, Charles Kubasta, Kimmo Kulonen, Frank ", - " Lackaff, Michael Lacour, Matt Lake, Jason Landry, Hans Erik ", - " Lange, Michael Laramee, Brad Lascelle, Pat Laschinger, Alan ", - " Lau, Sean Laurence, Anthony Lavey, Jr., Gary Le, Huey Le, ", - " Stephane Le Roy Audy, Lim Leandro, Charles Lee, Conroy Lee, ", - " Mike Lee, Shih-Hang Lee, Jonathan Leipert, Jason Lemann, ", - " Ron Lenzi, Mitchell Leon, Stephanie Lesniewski, Brendan ", - " Lewis, Robert Lewis, Sam Liao, Tom Liem, Adam Ligas, Steven ", - " Liggett, Roger Lilley, Benjamin Lim, Jeff Lindholm, Johnson ", - " Linwood, David Litchman, Bruce Lithimane, William Liu, ", - " Wilson Liu, Robert Lobdell, Chris Logan, Razvan Loghin, Jack ", - " Loh, George Loo, Russell Love, Juan Loyola, Ricardo Lozano, ", - " Mike Luban, Tim Luc, Henry Luciano, Dianne Ludwig, Charles ", - " Lueras, Derek Lung, Phong Ly, Scott MacGillivray, Dave Mack, ", - " Alec Mak, Steve Mamayek, Michael Mancini, Daniel Mann, ", - " Michael Mann, Chris Manofsky, Abdullah Marafie, Nicholas ", - " Marcy, Piompino Mariano, Bob Marius, Trey Marshall, Dane ", - " Martin, Gregg Martin, Renard Martin, Rich Martin, Scott ", - " Martin, Thomas Martin, Jon Masters, Christopher Mathews, ", - " Jay Mathis, Marc Matthews, Chris Mazur, Doug McBride, ", - " Mackey McCandlish, Robin McCollum, Steven McCombie, ", - " Andy McConnell, Michael McCourt, Bill McCoy, Doug ", - " McCracken, Michael McDeed, Robert McDonald, Steve ", - " McEachron, Craig McGee, Ryan McKenzie, Michael McKeown, ", - " Daniel McMahon, Colin McMillan, Ian McWilliam, Mark ", - " McWilliams, Khann Mean, Bryan Meason, Kenneth Medley, ", - " Jeff Meek, John Mehr, Christopher Mende, Brian Mendenhall, ", - " Peter Mengel, Michael Mersic, Mike Messom, Don Metcalf, ", - " Gary Metzker, Scott Meyer, Joseph Michaud, Andrew Mielke, ", - " Travis Mikalson, Troy Milburn, Ike Miller, Ronnie Miller, Sean ", - " Miller, Steve Miller, Arthur Min, David Minniti, Brenda ", - " Mirsberger, Bill Misek, David Mitchell, Joseph Mobley, Robert ", - " Mollard, Will Mooar, Curtis Moore, Matthew Moore, Al ", - " Morales, Ryan Moran, Lance Mortensen, Karel Mrazek, Ward ", - " Mullee, William Munoz, Kirk Munro, Craig Murray, Shawn P. ", - " Murray, Travis Murray, Michael Mushrush, Tom Mustaine, ", - " David Myers, Joseph Myett, Morgan Najar, Kenta Nakamura, ", - " Damian Nastri, Joshua Naumann, Nick Navarro, Douglas ", - " Neitzel, Arnold Ng, Anthony Nguyen, Steve Nguyen, Joseph ", - " Nicholas, Charles Nickolaus, Jon Nisbet, Patrick Nomee, David ", - " Norling-Christensen, Bobby Norton, Joseph Nottingham, Frank ", - " O'Connor, Jon Oden, David Oester, Lavern Ogden, Zach ", - " Oglesby, Lucas Oldfield, Toby Olsson, Aaron Ondek, Sean ", - " O'Neill, John Orlando, Samuel Orlando, Donovan Orloski, ", - " David Pai, Nikolas Paldan, David Palek, John Palmieri, Anthony ", - " Palmisano, Sanjay Pandit, Jesse Park, Alex Parker, Jimmy ", - " Pasher, Lukasz Paszek, Andy Patterson, William Pelletier, ", - " Duane Pemberton, Ivan Pemic, Kelly Pendergast, Mike ", - " Penezich, Jon Penk, Willie Penley, Ron Penna, Matthew ", - " Pennington, Kevin Pereira, Ross Perez, Ken Perkins, Brian ", - " Peterik, Kelly Peterson, Chris Phillips, Rod Pickett, Cameron ", - " Pierce, Reuben Pierce, Tim Pilger, Billy Pippin, Brad Plank, ", - " Brian Plant, Craig Platt, David Plunkett, Michael Politi, Albert ", - " Portillo, Brian Powell, David Powell, Franklin Powers Jr., Alan ", - " Precourt, Michael Pronchick, Julian Quintana, Justin Radziej, ", - " Steven Rajewski, Shawn Rawles, Ian Reardon, Marc Reed, Ric ", - " Reichelt, Judd Reiffin, David Reilly, Garry Reisky, Drew ", - " Ressler, Robert Reynolds, Walter Reynolds, Michael Rice, Ian ", - " Richards, James Richards, Raymond Richmond, Dustin Riggs, ", - " Keith Riskey, Brian Ro, Scott Roberts, Jorge Rodriguez, Chad ", - " Rogers, Clint Rogers, Robert Rogers, Steve Rogers, Ethan Roots, ", - " Ron Roque, William Ross, Sebastian Rossi, Jeff Rostis, Ben ", - " Roth, Demar Roth, Rich Rouse, Oleg Rovner, Jonathan Roy, ", - " Drew Rozema, Mike Ruggles, Mathias Russ, James Russell, Jim ", - " Rutledge, James Rutter, Dave Ryder, Chris Salvadras, Anders ", - " Samnerud, Nick Sanders, Jakob Sandgren, Joe Sapinsky, Tyler ", - " Sargent, Jonas Saunders, Mark Savage, Scott Sawyer, Robert ", - " Scanlon, Trevor Schaben, Aaron Schmidt, Chris Schmidt, Greg ", - " Schultz, Nicholas Schumacher, Scott Schumacher, Kevin Scott, ", - " Rastislav Seffer, Robert Seidler, Corey Sellers, Justin Sellers, ", - " Marc Senecal, George Shannon, Ian Sheffield, Anoop Shekar, ", - " Sandeep Shekar, Kevin Shelton, Leon Shephard, Eric Shepperd, ", - " Jeffrey Shneidman, Samuel Shockey, Mark Shoemaker, Mike ", - " Shupe, Sean Sibbet, Brian Sidharta, Jimmy Sieben, Eric ", - " Siemens, William Silva, Jody Simpson, Jatinder Singh, Sonia ", - " Siu, Omar Skarsvaag, Tom Skiba, Carl Skow, David Skuse, ", - " Robert Slifka, Brent Smith, C. Eric Smith, Jared Smith, Jeffrey ", - " Smith, Owen Smith, Shannon Smith, Steven Smith, Edward Smola, ", - " Matthew Sneep, Eric Snow, Brad Sobel, Jean-Pierre Solignac, Rasmus ", - " Sørensen, Andrew Sorg, Poppy Southcott, Ross Specter, Erik Spencer, ", - " Keith Spencer, Chris Springer, Erikson Squier, Dean St. Onge, Stewart ", - " Stanfield, John Stanley, Terrence Staton, Benjamin Stein, James ", - " Steiner, David Steyer, William Stickney, Chris Stiff, James Stofer, ", - " Norm Storch, Patrick Stovall, Brandon Sturgeon, Sean Stutler, Anne ", - " Sukprasert, Jamal Sullivan, Bruce Sully, Jay Sung, Park Sung ", - " Joon, Stein Sunnarvik, Nathan Surginer, Robert Swaringen, Lee ", - " Sweeney, David Szabo, Scott Taft, Christian Takvam, Patrick ", - " Talaska, Tadashi Tamaki, Simon Tan, Mark Taraba, Khon-", - " Whey Tay, John Taylor, Keith Taylor, Donald Temean, Phillip ", - " Tesar, Pete Thao, Brian Thomas, Keith Thomas, Speed Thomas, ", - " Miles Thorpe, Paul Thurrott, Mike Timbol, Nicholas Timmins, ", - " Tom Tobin, Robert Towster, Hien Tran, Timothy Traviss, Toby ", - " Traylor, Tony Treadwell, George Tremoulis, Paul Trinh, Thanh ", - " Trinh, Chris Tristan, Brad Truswell, Jason Tryon, Mike Tu, ", - " Gernel Tuazon, Eric Tuggle, Mike Turnbull, Lyle Ubben, ", - " Amilcar Ubiera, Robert Ulozas, Arie Upton, Mark Van Noy, ", - " Matthew Van Sickler, Jake Vantlin, Tony Vasquez, Brady ", - " Vauclin, Gianpiero Vecchi, Chad Verrall, Chris Vicente, Brett ", - " Vickers, David Vickery, Jonathan Vilante, Simon Vince, Ben ", - " Vinson, David Voelkert, Paul Vogt, Nicholas Voorhies, Robert ", - " Vreeland, Mike Vrooman, Rick Vuong, Brian Wachhaus, Todd ", - " Wachhaus, Caine Wade, Mathew Wadstein, Kenneth Wagenius, ", - " Trevor Wagner, John Wagstaff, Asad Wahid, Richard ", - " Wahlberg, Helio Wakasugui, Richard Walker, Wilkins Walker, ", - " Matthew Wallace, Daniel Walsh, Joel Walters, Andrew Waltz, ", - " Tom Wang, Tony Wang, Jay Ward, Jonathan Ward, John ", - " Warner, Mark Warren, Matt Washer, Mike Watson, Sean ", - " Wattles, Mike Wayne, Christian Wehba, Benjamin Wei, Richard ", - " Weight, Cary Wells, David Wenck, Bill Werring, Leonard ", - " Wesley, Marlon West, Mikael Westerbacka, Brian Wharry, ", - " Chris White, Chris White, Jeremy White, Greg Whitlock, Gary ", - " Widener, Marty Wilfried, Israel Wilkinson, Michael Willams, ", - " Derek Williams, Sean Willson, Nitzan Wilnai, Jim Wilson, ", - " Karsten Wilson, William Wilt, Tim Winn, Brian Winzeler, Matt ", - " Wise, Lee Wissmiller, Brendan Wolfe, Daniel Wolpert, Felix ", - " Wong, Power Wong, Tony Wong, Tim Wood, Timothy Wood, ", - " Jeremy Woods, Michael Woods, Bill Wright, Keith Wright, ", - " Patrick Wu, Gang Xie, Robert Yao, Sun Lim Yap, Stephen Yau, ", - " Erek Yedwabnick, Christopher Yee, Nick Yee, Juan Yip, David ", - " Young, Rob Young, Seth Young, Alex Yu, Terry Zahn, Jia-Ning ", - " Zhang, Eric Zieg, Jordan Zielin, Clint Zimmerman, Matt Zinke ", - "", - "", - "", - "", - " No souls were sold in the making of this game.", - "", - "", - " ", - " ", - " " + "RECORDING ENGINEER", + " ROBERT KOENIGSBERG", + "", + "MANUAL DESIGN & LAYOUT", + " PETER UNDERWOOD, JEFFREY VAUGHN,", + " CHRIS METZEN, BILL ROPER", + "", + "MANUAL ARTWORK", + " SAMWISE DIDIER, CHRIS METZEN,", + " ROMAN KENNEY, MAXX MARSHALL", + "", + "PROVISIONAL DIRECTOR OF QA (LEAD TESTER)", + " SHANE DABIRI", + "", + "QA ASSAULT TEAM (TESTERS)", + " CHRISTOPHER CROSS, MIKE GIVENS, DAVE HALE,", + " BRIAN \"DOC\" LOVE, HUNG NGUYEN, DEAN SHIPLEY,", + " CHRIS SIGATY, IAN WELKE, JAMIE WIGGS", + "", + "QA SPECIAL OPS TEAM (COMPATIBILITY TESTERS)", + " ADAM MAXWELL, RUSSELL \"RUG\" MILLER", + "", + "QA ARTILLERY SUPPORT (ADDITIONAL TESTERS) ", + " RICH ALCAZAR, MIKE JONES, REV. DAN MOORE, MATT MORRIS,", + " MARK PFEIFFER, HARISH \"PEPE THE ENFORCER\" RAO, CHRIS MILLAR", + "", + "QA COUNTERINTELLIGENCE", + " ALAN DABIRI, JESSE MCREYNOLDS, WALTER TAKATA", + "", + "ORDER OF NETWORK INFORMATION SERVICES", + " ROBERT BRIDENBECKER, JASON \"BROTHER SHAGGY\" SCHMIT,", + " JAMIE \"BROTHER GUG\" STEIGERWALD, RICHARD SEIS ", + "", + "CUSTOMER SUPPORT", + " JOHN SCHWARTZ, VIC LARSON, CHAD CHAUDRY, MICK YANKO,", + " BRANDON RISELING, KIRK MAHONY, TONY HARDY, RICHARD", + " AMTOWER, COLLIN SMITH, ANDREW EDWARDS, ROGER EBERHART", + "", + "SALES", + " JORGE RIVERO, ROB BEATIE", + "", + "DUNSEL", + " ALAN DABIRI", + "", + "MR. DABIRI'S BACKGROUND VOCALISTS", + " KARIN COLENZO, CHRISTINA CADE,", + " KIM FARRINGTON, MELISSA EDWARDS", + "", + "PUBLIC RELATIONS", + " LINDA DUTTENHAVER, SUSAN WOOLEY", + "", + "MARKETING", + " JOHN PATRICK, STEVE HUOT, NEAL HUBBARD, KATHY CARTER", + "", + "INTERNATIONAL SALES", + " RALPH BECKER, CHRIS YOSHIMURA", + "", + "U.S. SALES", + " TODD COYLE, DANNY KEARNS", + "", + "MANUFACTURING", + " JOHN GOODMAN, TOM BRYAN", + "", + "LEGAL & BUSINESS", + " PAULA DUFFY, ERIC ROEDER, PAUL SAMS, KENNETH WILLIAMS", + "", + "SPECIAL THANKS TO", + " PRIMENET, EARTHLINK, AOL, COMPUSERVE, ATI, MATROX, STB, ", + " CREATIVE LABS, LOGITECH, U.S. ROBOTICS, GRAVIS, CYRIX", + "", + "THANKS TO", + " IAN COLQUHOUN, ROD SHEAN, BRIAN FITZGERALD, SHARON SCHAFER, TODD ", + " SCHAFER, RICHARD AND SANDRA SCHAEFER, RICK BOWLES, GREG BOGDEN, ", + " CINDY SIEVERT, BRAD MASON, CHUCK GOLDMAN, KARIN COLENZO, WENDY ", + " BREVIK, JENNIE BREVIK, HANNA CARROLL, KATIE NEWELL, KAREN WEISS, ", + " KURT BEAVER, STAN MCDONALD, BRIAN SEXTON, MICHAEL WAN, MEGAN ", + " WILLIAMS, JESSICA GENSLEY, BETH ANN PARKS, BRIAN PILTIN, JOHNATHAN ", + " ROOT, BRETT SUPERNAW, SABEER BHATIA, MARK REARICK, BRAD MASON, ", + " DIANE KODAMA, BERNADETTE SEXTON, BARBARA UHLMANN, PATRICIA", + " MCDONALD, KRIS KELLEY, ALISSA VAAGE, DENISE HERNANDEZ, PAULA ", + " WHITE, RACHEL MARIE HAWLEY, LAURA GABER, ISAAC MATARASSO,", + " SUSAN STAFFORD, GRETCHEN WITTE, JASON SAILOR, EUFEMIA PALOMINO, ", + " NATHALIE DIDIER, NICOLE WELKE, DAWN CADDEL, ANNA-MARCELLE ", + " OKAMURA, AMBER OKAMURA, MEGAN OKAMURA TRACEY MCNAUGHTON, ", + " TRISHA ANN OCHOA, ANNIE STRAIN, DR. GREGORY T. STREET, RAY THE SODA ", + " GUY, SAM RAIMI, A. GUINNESS BREWING CO., JOHN WOO, CHOW YUN FAT, ", + " JACKIE CHAN,PROPOSITION 215, RUMIKO TAKAHASHI, BUNCHY & MASON, ", + " THE FRIENDS OF STAN, THE ZOO CREW, TEAM HAMRO, BRAZIL 2001, RUSH, ", + " CORNHOLIO, THE BROS., DAR, EMERIL LAGASSE, TOM WAITS, ICE-CUBE, ", + " THE STRIKE TEAM DEFLECTORS, TONY LEVIN, BIG JIM AND THE TWINS, ", + " JAG`RMEISTER, THE MEGASPHERE, CONDOR, THE ALLOWER, THE SUNDAY ", + " NIGHT GROUP, GRAVITAR, STEINWAY PIANOS, ROUND TABLE PIZZA, THE POXY ", + " BOGGARDS, URBAN MYSTIC & CO., CAFFEINE, HUNTER ROSE, MARLY ", + " MEDIUMS IN THE BOX, SWEET POTEEN, DAVE SCARPITTI, THEBYTER, BIM ", + " MAN, KRISSANN FOR COLOR, PATTY AT AVALON TATTOO, JAMES, WHALEBOY, ", + " DUNSEL TRAINING INSTITUTE, MONKEYS, DOB BOLE, ROOTES GROUP, PORSHE, ", + " BONGO, SCARLETT, APOLLO, THE HOUSE OF MEDIOCRITY, AMELIAS, THE KING, ", + " SAAG AND ALL THE FOLKS AT DAVIDSON", + "", + "IN MEMORY OF", + " LAWRENCE AND BARBARA WILLIAMS", + " DAVID A. HARGRAVE", + " TONY \"XATRE\" COLLIN", + " THOMAS H SEXTON", + "", + "VERY SPECIAL THANKS TO", + " BOB AND JAN DAVIDSON", + " WALTER FORBES", + "", + "THE RING OF ONE THOUSAND", + " ANDREW ABERNATHY, CHRISTOPHER ABRAMO, DAVID ADAMS, DAVID ", + " ADCOX, MARKO AGTERBERG, CORY AIKEN, JUDAH ALTARAS, JOHN ", + " ALVAREZ, JOSE ALVAREZ, RICHARD AMABLE, ALEXANDER AMARAL, ", + " SCOTT AMIS, VINCENT AMOROSO, MARK AN, DAVID ANDERSEN, JASON ", + " ANDREW ABERNATHY, CHRISTOPHER ABRAMO, DAVID ADAMS, DAVID ", + " ADCOX, MARKO AGTERBERG, CORY AIKEN, JUDAH ALTARAS, JOHN ", + " ALVAREZ, JOSE ALVAREZ, RICHARD AMABLE, ALEXANDER AMARAL, ", + " SCOTT AMIS, VINCENT AMOROSO, MARK AN, DAVID ANDERSEN, JASON ", + " ANDERSEN, AARON ANDERSON, GEORGE ANDERSON, MATTHEW ", + " ANDERSON, MICHAEL ANDERSON, SEAN ANDERSON, ROBERT ANDRADE, ", + " CERNY ANDRE, MICHAEL ANDREEV, DEVIN ANGLE, BRIAN APPLE, ", + " BRIAN ARBUTHNOT, BILLY ARDEN, DORIAN ARNOLD, ANDRE ARSENAULT, ", + " ERIK ASPLUND, MARK ASSAM, JOHN ATHEY, JASON ATTARD, JEFF ", + " ATWOOD, RICKY AU, SCOTT AVERY, RAND BABCOCK, STEVE BABEL, ", + " RAYMOND BACALSO, ED BACHTA, STEVEN BACK, SCOTT BAEDER, ALEX ", + " BAEVSKI, SCOTT BAILEY, KENNETH BAIRD, THOMAS BAKER, TODD ", + " BALA, JAN BALL, GREG BALTZ, BLAKE BALTZLEY, DOUG BAMBRICK, WES ", + " BANGERTER, PAUL BARFUSS, CHRIS BARGHOUT, DAVE BARNEBEY, JON ", + " BARNHART, TERJE BARTH, NICOLE BASKIN, BERNARD BAYLEN, RYAN ", + " BEAR, PHIL BEDARD, TODD BELCHER, CHIP BELL, EREZ BEN-AHARON, ", + " JONATHAN BENDER, NICK BENNETT, IRENEY BEREZNIAK, TED BERG, ", + " GUNNAR BERGEM, RUSSELL BEUKER, ED BICKFORD, STEPHEN BILES, ", + " JOHN BILLDT, GERALD BINDER, JOHN BIRD, HANNAH BLACKERBY, TOM ", + " BLACKERBY, CLAYTON BLACKWELL, THOMAS BLAKE, SHAWN BLASZAK, ", + " DANIEL BLISS, FRED BLISS, JEFF BLISS, JON BLUM, RUNE BOERSJOE, ", + " ANDREW BOGGS, DAVE BOISVENU, JOE BOLT, JOHN BONDS, JEFF ", + " BORENSTEIN, DORIAN BORIN, ED BORIS, BARTHOLOMEW BOTTA, ", + " MICHAEL BOUTIN, MICHAEL BOYD, CHARLES BOYER, MIKE ", + " BOYERSMITH, MICHAEL BOYKO, ERIC BRADBERRY, JOHN BRANDSTETTER, ", + " RYAN BREDING, PAUL BRINKMANN, PATRICK BRISCOE, SCOTT BRISKO, ", + " JEREMY BRITTON, ADRIAN BROADHEAD, GLENN BROUWER, JOE BROWN, ", + " SÉBASTIEN BRULOTTE, DARRELL BRUNSCH, WILLIAM BRYAN, JASON ", + " BUCHER, CHRIS BUCHINGER, CLAYTON BUCKINGHAM, JOHN BUCKLES, ", + " DAVID BUGAY, ED BUJONE, ERIK BURGESS, GABRIEL BURKETT, CHRIS ", + " BURNES, RICHARD BUTLER, JEFFREY BYE, DOUGALL CAMPBELL, DONNIE ", + " CANNON, SHANE CANTRELL, CONNOR CAPLE, DANIEL CAREY, JAMES ", + " CARLTON, MICHAEL CARMEL, MIKE CARPENTER, RONALD CARRUTHERS, ", + " PHIL CARTER, BRYCE CARTMILL, ERIC CARTWRIGHT, ANTHONY CARUSO, ", + " LON CASEY, TIM CASTER, AARON CHAN, OTTO CHAN, GENE CHANG, ", + " HSIAO-LUNG CHANG, WILLIAM CHANG, GEORGE CHAPPEL, LARRY ", + " CHARBONNEAU, TROY CHASE, BRUCE CHEN, CHUN HSIEN CHEN, SAM ", + " CHEN, TZU-MAINN CHEN, MIKE CHENG, CHRIS CHIAPUSIO, DAMIEN ", + " CHIESA, NICK CHIN, NIM CHING, JONATHAN CHINN, MICHAEL CHINN, ", + " PHILANDER CHIU, THAYNE CHRISTIANSEN, PHILIP CHUI, STEVE ", + " CINTAMANI, RICHARD CIORDIA, COLIN CLARK, STEVE CLARK, SAMUEL ", + " CLEMENTS, MEREDITH CLIFTON, JEFF COHEN, DALE COLTON, DAX ", + " COMBE, MATT COMPTON, JACOB CONKLIN, RICHARD CONN, ZAC ", + " COOK, TIM COOLONG, GREGORY COOMER, DENNIS COSGROVE, KELLY ", + " COUCH, ANDREW COULTER, ERIC COUTINHO, DAVID COUTTS, JAMES ", + " CRAIG, JOHN CRAIG, KAZIAL CRAIG, JOHN CRAWFORD, MARCELO ", + " CRESPO, ORVILLE CREWS, TIM CRISTY, ELMER CROSBY III, RUSSELL ", + " CULLISON, RYAN CUPPLES, ANDREW DAGLEY, STEVE DALLAIRE, RICHARD ", + " DALTON, DAVID DANDAR, PRO DAULO, ROB DAUTERMANN, MIKE ", + " DAVIES, KALIEB DAVIS, MARSHALL DAVIS, RONALD DAVIS, DANNY DE ", + " BIE, MARC DE FILIPPIS, MYLES DEIGHTON, KENT DEJARNETT, ANTHONY ", + " DELAROSA, NEIL DEMPSTER, PETER DENITTO, JOAQUIM DENTZ, SCOTT ", + " DEWAR, ANISH DHINGRA, PHILIP DHINGRA, DAVID DIAZ, STEWART ", + " DICKS, BRAD DIETZ, JOSH DIETZ, COLLEEN DIGGINS, MIKE DITCHBURN, ", + " ERIC DITTMAN, ALLEN DO, HUY DOAN, MATTHEW DOLMAN, ANTOINE ", + " DONGOIS, EAMONN DONOHOE, BILL DORELL, MARK DORISON, DAN ", + " DORSETT, CHRIS DORSEY, JIM DOSÉ, WILLIS DOSS, CHIN DU, WILLIAM ", + " DUBIS, TIMOTHY DUEWELL, BRANDON DUNN, ANDREW DURHAM, DON ", + " DUVALL, KEVIN DVOJACK, DANIEL EATON, PAUL EBERTING, ERIC ", + " ECHELBARGER, LANCE EDDLEMAN, BEN EGGERS, DAVID EGGUM, JOHN ", + " EHDE, BRIAN EIKENBERRY, PATRICK ELVEN, PETER ENGDAHL, PHILIP ", + " ENGDAHL, MICHAEL ENNIS, DARREN ESLINGER, ERIC EZELL, DARREN ", + " FALSLEV, STEPHEN FEATHER, TONY FENN, BEN FERGUSON, MIKE ", + " FERNANDEZ, GWENDAL FEUILLET, GUY FIETZ, JULIAN FIGUEROA, DALE ", + " FILLPOT, STAN FINCHEM, MICHAEL FINLEY, NICK FISHER, WILLIAM ", + " FISHER, MARK FITLIN, DAVE FLATT, JOEL J. FLORES, JOHN FOLKERS, ", + " STEVEN FORGIE, TOM FORSYTHE, MATTHEW FOSTER, SCOTT FRANCIS, ", + " JIM FRANK, PAULO FRASER, GLENN FRENCH, KURT FRERICHS, CHRIS ", + " FREY, MARK FRIEDMAN, CHARLES FRIEDMANN, DAN FRIEND, KIRK ", + " FRY, AARON FU, ERIK GAALEMA, BRANDON GABBARD, PHIL GAGNER, ", + " TOMMY GANNON, DAVID GAPPMAYER, CHRIS GARRISON, TONY ", + " GARRISON, DAVID GASCA, JEREMY GASSER, MICHAEL GEIST, MICHAEL ", + " GENEREUX, DANIEL GENOVESE, JOSH GERWIN, PAUL GIBSON, WILLIAM ", + " GILCHRIST, GABRIEL GILS CARBO, CHAD GLENDENIN, RYAN GLINSKI, ", + " DEAN GOBRECHT, ANDREW GOLDFINCH, DAVID GOODMAN, MARK ", + " GOODSON, MATT GORDON, FRANK GORGENYI, SEAN GOULD, PERRY ", + " GOUTSOS, ED GOVEDNIK, MICHAEL GRAYSON, CHRIS GREEN, JUSTIN ", + " GRENIER, JEFF GREULICH, DON GREY, ROB GRIESBECK, DON GRIFFES, ", + " KIMBERLY GRIFFETH, JAY GRIZZARD, DON GRONLUND, JOE GROSS, ", + " TROY GROWDEN, GREG GUILFORD, DAVID GUSOVSKY, JEREMY ", + " GUTHRIE, ADAM GUTIERREZ, JAMES GUZICKI, MATTHEW HAAS, MATT ", + " HADLEY, RYAN HAGELSTROM, BOBBY HAGEN, BEN HALL, BRIAN HALL, ", + " KRIS HALL, CALVIN HAMILTON, KRIS HAMILTON, BO HAMMIL, DAVE ", + " HANS, RICK HANSEN, ROBERT HARLAN, TRAVIS HARLAN, SETH ", + " HARMAN, JEFF HARRIS, SHAWN HARTFORD, ADAM HARTSELL, NEIL ", + " HARVEY, RAY HAYES, JOHN HEIN, CHRIS HEINONEN, CHRISTER ", + " HELSING, CHRIS HEMPEL, DUSTIN HEMPEL, MATHIEU HENAIRE, MATT ", + " HENRY, CHUCK HERB, MICHAEL HERRON, SAGE HERRON, THOMAS ", + " HERSCHBACH, CLIFF HICKS, NELSON HICKS, PAUL HIERLING, WILLIAM ", + " HIERS, MIKE HIGDON, TIM HILDEBRAND, CASEY HINKLE, RYAN ", + " HITCHINGS, WES HIX, ALAN HO, JENSON HO, ALAN HOFFMAN, JEFF ", + " HOFFMAN, ELEANOR HOFFMANN, STEVE HOGG, RICHARD HOLLER, BRIAN ", + " HOMOLYA, WADE HONE, JOE HORVATH, JEFF HOWE, ERIC HUDSON, ", + " GLEN HUEY, CHRIS HUFNAGEL, JOSHUA HUGHES, MELISSA HUGHES, ", + " ARIEF HUJAYA, THOMAS HULEN, RYAN HUPP, JUSTIN HURST, RICK ", + " HUTCHINS, STEVE IAMS, MIKE IAROSSI, BJORN IDREN, JOHAN IDRÉN, ", + " MICAH IMPARATO, JOE INGERSOLL, DAVID INGRAM, GREG IPP, RODNEY ", + " IRVIN, DARIN ISOLA, JUSTIN ITOH, MARIO IVAN, FREDRIK IVARSSON, ", + " DAX JACOBSON, MICHAEL JACQUES, STEVENS JACQUES, DUANE JAHNKE, ", + " WILLIAM JAMBROSEK, DANIEL JANICK, NARCISO JARAMILLO, NEIL ", + " JARIWALA, HARVIE JARRIELL, SCOTT JAVADI, JOE JENKINS, BART ", + " JENNINGS, PAUL JENNINGS, JULIEN JENNY, JASON JENSEN, MARTIN ", + " JEREMY, MARK JESCHKE, ANDY JOHNSON, JAMES JOHNSON, LEIGH ", + " JOHNSON, MARK JOHNSON, RUPERT JOHNSON, CLYDE JONES, MICHAEL ", + " JONES, TIM JORDAN, BEN JUDY, MICHAEL KAAE, STEVE KACZKOWSKI, ", + " NEVILLE KADWA, BRIAN KAISNER, YOSHIHISA KAMEYAMA, MICHAEL ", + " KANEMURA, DANIEL KAO, ERIC KARABIN, BEN KATZ, CHRISTOPHER ", + " KAWAMURA, ERICK KAYSER, CRAIG KEDDIE, KEVIN KELLEY, BRYAN ", + " KEMP, MICHAEL KENDRIGAN, DAN KERBER, TIMOTHY KERBER, TOMI ", + " KESKI-HEIKKILÄ, GREG KETTERING, NATHAN KILBER, HOWARD KIM, ", + " ORRIN KINION, JON KIRST, DAVID KITCH, JOHN KLINGBEIL, NEIL ", + " KLOPFENSTEIN, KERRY KNOUSE, DAVID KNOX, SAID KOBEISSI, JEFF ", + " KOCHES, HADES KONG, JEFF KONG, KEVIN KONKLE, STEVE KOON, ", + " DAVID KOONTZ, DAN KOOPMANN, STEVE KOSKELA, KUAN KOU, ", + " CAMERON KRACKE, JENSEN KRAGE, YORK KRAMER, CEDAR KRAUS, ", + " JASON KRAUS, BOBBY KRIMEN, MELISSA KRISPLI, STEVEN KRISPLI, ", + " JAMES KRUGER, CHARLES KUBASTA, KIMMO KULONEN, FRANK ", + " LACKAFF, MICHAEL LACOUR, MATT LAKE, JASON LANDRY, HANS ERIK ", + " LANGE, MICHAEL LARAMEE, BRAD LASCELLE, PAT LASCHINGER, ALAN ", + " LAU, SEAN LAURENCE, ANTHONY LAVEY, JR., GARY LE, HUEY LE, ", + " STEPHANE LE ROY AUDY, LIM LEANDRO, CHARLES LEE, CONROY LEE, ", + " MIKE LEE, SHIH-HANG LEE, JONATHAN LEIPERT, JASON LEMANN, ", + " RON LENZI, MITCHELL LEON, STEPHANIE LESNIEWSKI, BRENDAN ", + " LEWIS, ROBERT LEWIS, SAM LIAO, TOM LIEM, ADAM LIGAS, STEVEN ", + " LIGGETT, ROGER LILLEY, BENJAMIN LIM, JEFF LINDHOLM, JOHNSON ", + " LINWOOD, DAVID LITCHMAN, BRUCE LITHIMANE, WILLIAM LIU, ", + " WILSON LIU, ROBERT LOBDELL, CHRIS LOGAN, RAZVAN LOGHIN, JACK ", + " LOH, GEORGE LOO, RUSSELL LOVE, JUAN LOYOLA, RICARDO LOZANO, ", + " MIKE LUBAN, TIM LUC, HENRY LUCIANO, DIANNE LUDWIG, CHARLES ", + " LUERAS, DEREK LUNG, PHONG LY, SCOTT MACGILLIVRAY, DAVE MACK, ", + " ALEC MAK, STEVE MAMAYEK, MICHAEL MANCINI, DANIEL MANN, ", + " MICHAEL MANN, CHRIS MANOFSKY, ABDULLAH MARAFIE, NICHOLAS ", + " MARCY, PIOMPINO MARIANO, BOB MARIUS, TREY MARSHALL, DANE ", + " MARTIN, GREGG MARTIN, RENARD MARTIN, RICH MARTIN, SCOTT ", + " MARTIN, THOMAS MARTIN, JON MASTERS, CHRISTOPHER MATHEWS, ", + " JAY MATHIS, MARC MATTHEWS, CHRIS MAZUR, DOUG MCBRIDE, ", + " MACKEY MCCANDLISH, ROBIN MCCOLLUM, STEVEN MCCOMBIE, ", + " ANDY MCCONNELL, MICHAEL MCCOURT, BILL MCCOY, DOUG ", + " MCCRACKEN, MICHAEL MCDEED, ROBERT MCDONALD, STEVE ", + " MCEACHRON, CRAIG MCGEE, RYAN MCKENZIE, MICHAEL MCKEOWN, ", + " DANIEL MCMAHON, COLIN MCMILLAN, IAN MCWILLIAM, MARK ", + " MCWILLIAMS, KHANN MEAN, BRYAN MEASON, KENNETH MEDLEY, ", + " JEFF MEEK, JOHN MEHR, CHRISTOPHER MENDE, BRIAN MENDENHALL, ", + " PETER MENGEL, MICHAEL MERSIC, MIKE MESSOM, DON METCALF, ", + " GARY METZKER, SCOTT MEYER, JOSEPH MICHAUD, ANDREW MIELKE, ", + " TRAVIS MIKALSON, TROY MILBURN, IKE MILLER, RONNIE MILLER, SEAN ", + " MILLER, STEVE MILLER, ARTHUR MIN, DAVID MINNITI, BRENDA ", + " MIRSBERGER, BILL MISEK, DAVID MITCHELL, JOSEPH MOBLEY, ROBERT ", + " MOLLARD, WILL MOOAR, CURTIS MOORE, MATTHEW MOORE, AL ", + " MORALES, RYAN MORAN, LANCE MORTENSEN, KAREL MRAZEK, WARD ", + " MULLEE, WILLIAM MUNOZ, KIRK MUNRO, CRAIG MURRAY, SHAWN P. ", + " MURRAY, TRAVIS MURRAY, MICHAEL MUSHRUSH, TOM MUSTAINE, ", + " DAVID MYERS, JOSEPH MYETT, MORGAN NAJAR, KENTA NAKAMURA, ", + " DAMIAN NASTRI, JOSHUA NAUMANN, NICK NAVARRO, DOUGLAS ", + " NEITZEL, ARNOLD NG, ANTHONY NGUYEN, STEVE NGUYEN, JOSEPH ", + " NICHOLAS, CHARLES NICKOLAUS, JON NISBET, PATRICK NOMEE, DAVID ", + " NORLING-CHRISTENSEN, BOBBY NORTON, JOSEPH NOTTINGHAM, FRANK ", + " O'CONNOR, JON ODEN, DAVID OESTER, LAVERN OGDEN, ZACH ", + " OGLESBY, LUCAS OLDFIELD, TOBY OLSSON, AARON ONDEK, SEAN ", + " O'NEILL, JOHN ORLANDO, SAMUEL ORLANDO, DONOVAN ORLOSKI, ", + " DAVID PAI, NIKOLAS PALDAN, DAVID PALEK, JOHN PALMIERI, ANTHONY ", + " PALMISANO, SANJAY PANDIT, JESSE PARK, ALEX PARKER, JIMMY ", + " PASHER, LUKASZ PASZEK, ANDY PATTERSON, WILLIAM PELLETIER, ", + " DUANE PEMBERTON, IVAN PEMIC, KELLY PENDERGAST, MIKE ", + " PENEZICH, JON PENK, WILLIE PENLEY, RON PENNA, MATTHEW ", + " PENNINGTON, KEVIN PEREIRA, ROSS PEREZ, KEN PERKINS, BRIAN ", + " PETERIK, KELLY PETERSON, CHRIS PHILLIPS, ROD PICKETT, CAMERON ", + " PIERCE, REUBEN PIERCE, TIM PILGER, BILLY PIPPIN, BRAD PLANK, ", + " BRIAN PLANT, CRAIG PLATT, DAVID PLUNKETT, MICHAEL POLITI, ALBERT ", + " PORTILLO, BRIAN POWELL, DAVID POWELL, FRANKLIN POWERS JR., ALAN ", + " PRECOURT, MICHAEL PRONCHICK, JULIAN QUINTANA, JUSTIN RADZIEJ, ", + " STEVEN RAJEWSKI, SHAWN RAWLES, IAN REARDON, MARC REED, RIC ", + " REICHELT, JUDD REIFFIN, DAVID REILLY, GARRY REISKY, DREW ", + " RESSLER, ROBERT REYNOLDS, WALTER REYNOLDS, MICHAEL RICE, IAN ", + " RICHARDS, JAMES RICHARDS, RAYMOND RICHMOND, DUSTIN RIGGS, ", + " KEITH RISKEY, BRIAN RO, SCOTT ROBERTS, JORGE RODRIGUEZ, CHAD ", + " ROGERS, CLINT ROGERS, ROBERT ROGERS, STEVE ROGERS, ETHAN ROOTS, ", + " RON ROQUE, WILLIAM ROSS, SEBASTIAN ROSSI, JEFF ROSTIS, BEN ", + " ROTH, DEMAR ROTH, RICH ROUSE, OLEG ROVNER, JONATHAN ROY, ", + " DREW ROZEMA, MIKE RUGGLES, MATHIAS RUSS, JAMES RUSSELL, JIM ", + " RUTLEDGE, JAMES RUTTER, DAVE RYDER, CHRIS SALVADRAS, ANDERS ", + " SAMNERUD, NICK SANDERS, JAKOB SANDGREN, JOE SAPINSKY, TYLER ", + " SARGENT, JONAS SAUNDERS, MARK SAVAGE, SCOTT SAWYER, ROBERT ", + " SCANLON, TREVOR SCHABEN, AARON SCHMIDT, CHRIS SCHMIDT, GREG ", + " SCHULTZ, NICHOLAS SCHUMACHER, SCOTT SCHUMACHER, KEVIN SCOTT, ", + " RASTISLAV SEFFER, ROBERT SEIDLER, COREY SELLERS, JUSTIN SELLERS, ", + " MARC SENECAL, GEORGE SHANNON, IAN SHEFFIELD, ANOOP SHEKAR, ", + " SANDEEP SHEKAR, KEVIN SHELTON, LEON SHEPHARD, ERIC SHEPPERD, ", + " JEFFREY SHNEIDMAN, SAMUEL SHOCKEY, MARK SHOEMAKER, MIKE ", + " SHUPE, SEAN SIBBET, BRIAN SIDHARTA, JIMMY SIEBEN, ERIC ", + " SIEMENS, WILLIAM SILVA, JODY SIMPSON, JATINDER SINGH, SONIA ", + " SIU, OMAR SKARSVAAG, TOM SKIBA, CARL SKOW, DAVID SKUSE, ", + " ROBERT SLIFKA, BRENT SMITH, C. ERIC SMITH, JARED SMITH, JEFFREY ", + " SMITH, OWEN SMITH, SHANNON SMITH, STEVEN SMITH, EDWARD SMOLA, ", + " MATTHEW SNEEP, ERIC SNOW, BRAD SOBEL, JEAN-PIERRE SOLIGNAC, RASMUS ", + " SØRENSEN, ANDREW SORG, POPPY SOUTHCOTT, ROSS SPECTER, ERIK SPENCER, ", + " KEITH SPENCER, CHRIS SPRINGER, ERIKSON SQUIER, DEAN ST. ONGE, STEWART ", + " STANFIELD, JOHN STANLEY, TERRENCE STATON, BENJAMIN STEIN, JAMES ", + " STEINER, DAVID STEYER, WILLIAM STICKNEY, CHRIS STIFF, JAMES STOFER, ", + " NORM STORCH, PATRICK STOVALL, BRANDON STURGEON, SEAN STUTLER, ANNE ", + " SUKPRASERT, JAMAL SULLIVAN, BRUCE SULLY, JAY SUNG, PARK SUNG ", + " JOON, STEIN SUNNARVIK, NATHAN SURGINER, ROBERT SWARINGEN, LEE ", + " SWEENEY, DAVID SZABO, SCOTT TAFT, CHRISTIAN TAKVAM, PATRICK ", + " TALASKA, TADASHI TAMAKI, SIMON TAN, MARK TARABA, KHON-", + " WHEY TAY, JOHN TAYLOR, KEITH TAYLOR, DONALD TEMEAN, PHILLIP ", + " TESAR, PETE THAO, BRIAN THOMAS, KEITH THOMAS, SPEED THOMAS, ", + " MILES THORPE, PAUL THURROTT, MIKE TIMBOL, NICHOLAS TIMMINS, ", + " TOM TOBIN, ROBERT TOWSTER, HIEN TRAN, TIMOTHY TRAVISS, TOBY ", + " TRAYLOR, TONY TREADWELL, GEORGE TREMOULIS, PAUL TRINH, THANH ", + " TRINH, CHRIS TRISTAN, BRAD TRUSWELL, JASON TRYON, MIKE TU, ", + " GERNEL TUAZON, ERIC TUGGLE, MIKE TURNBULL, LYLE UBBEN, ", + " AMILCAR UBIERA, ROBERT ULOZAS, ARIE UPTON, MARK VAN NOY, ", + " MATTHEW VAN SICKLER, JAKE VANTLIN, TONY VASQUEZ, BRADY ", + " VAUCLIN, GIANPIERO VECCHI, CHAD VERRALL, CHRIS VICENTE, BRETT ", + " VICKERS, DAVID VICKERY, JONATHAN VILANTE, SIMON VINCE, BEN ", + " VINSON, DAVID VOELKERT, PAUL VOGT, NICHOLAS VOORHIES, ROBERT ", + " VREELAND, MIKE VROOMAN, RICK VUONG, BRIAN WACHHAUS, TODD ", + " WACHHAUS, CAINE WADE, MATHEW WADSTEIN, KENNETH WAGENIUS, ", + " TREVOR WAGNER, JOHN WAGSTAFF, ASAD WAHID, RICHARD ", + " WAHLBERG, HELIO WAKASUGUI, RICHARD WALKER, WILKINS WALKER, ", + " MATTHEW WALLACE, DANIEL WALSH, JOEL WALTERS, ANDREW WALTZ, ", + " TOM WANG, TONY WANG, JAY WARD, JONATHAN WARD, JOHN ", + " WARNER, MARK WARREN, MATT WASHER, MIKE WATSON, SEAN ", + " WATTLES, MIKE WAYNE, CHRISTIAN WEHBA, BENJAMIN WEI, RICHARD ", + " WEIGHT, CARY WELLS, DAVID WENCK, BILL WERRING, LEONARD ", + " WESLEY, MARLON WEST, MIKAEL WESTERBACKA, BRIAN WHARRY, ", + " CHRIS WHITE, CHRIS WHITE, JEREMY WHITE, GREG WHITLOCK, GARY ", + " WIDENER, MARTY WILFRIED, ISRAEL WILKINSON, MICHAEL WILLAMS, ", + " DEREK WILLIAMS, SEAN WILLSON, NITZAN WILNAI, JIM WILSON, ", + " KARSTEN WILSON, WILLIAM WILT, TIM WINN, BRIAN WINZELER, MATT ", + " WISE, LEE WISSMILLER, BRENDAN WOLFE, DANIEL WOLPERT, FELIX ", + " WONG, POWER WONG, TONY WONG, TIM WOOD, TIMOTHY WOOD, ", + " JEREMY WOODS, MICHAEL WOODS, BILL WRIGHT, KEITH WRIGHT, ", + " PATRICK WU, GANG XIE, ROBERT YAO, SUN LIM YAP, STEPHEN YAU, ", + " EREK YEDWABNICK, CHRISTOPHER YEE, NICK YEE, JUAN YIP, DAVID ", + " YOUNG, ROB YOUNG, SETH YOUNG, ALEX YU, TERRY ZAHN, JIA-NING ", + " ZHANG, ERIC ZIEG, JORDAN ZIELIN, CLINT ZIMMERMAN, MATT ZINKE ", + "", + "", + "", + "", + " NO SOULS WERE SOLD IN THE MAKING OF THIS GAME.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", }; const std::size_t CREDITS_LINES_SIZE = sizeof(CREDITS_LINES) / sizeof(CREDITS_LINES[0]); diff --git a/SourceX/DiabloUI/fonts.cpp b/SourceX/DiabloUI/fonts.cpp index 1c67ecbc0..326d65eb8 100644 --- a/SourceX/DiabloUI/fonts.cpp +++ b/SourceX/DiabloUI/fonts.cpp @@ -60,7 +60,7 @@ void LoadTtfFont() { was_fonts_init = true; } - font = TTF_OpenFont(TTF_FONT_PATH, 17); + font = TTF_OpenFont(TTF_FONT_PATH, 13); if (font == NULL) { SDL_Log("TTF_OpenFont: %s", TTF_GetError()); return; diff --git a/SourceX/display.cpp b/SourceX/display.cpp index cb5d6fc11..9b3ebd594 100644 --- a/SourceX/display.cpp +++ b/SourceX/display.cpp @@ -1,6 +1,7 @@ #include "display.h" #include "DiabloUI/diabloui.h" #include "controls/controller.h" +#include // sleep(); sysconf(); for multithreading #ifdef USE_SDL1 #ifndef SDL1_VIDEO_MODE_BPP @@ -17,6 +18,8 @@ #endif #endif +int processors; /* for calculating the number of cpu cores*/ + namespace dvl { extern BOOL was_window_init; /** defined in dx.cpp */ @@ -68,6 +71,10 @@ bool SpawnWindow(const char *lpWindowName, int nWidth, int nHeight) int grabInput = 1; DvlIntSetting("grab input", &grabInput); + /* calculate the number of cpu cores for multithreaded operations */ + processors = sysconf(_SC_NPROCESSORS_ONLN); + /* calculate the number of cpu cores for multithreaded operations */ + #ifdef USE_SDL1 SDL_WM_SetCaption(lpWindowName, WINDOW_ICON_NAME); const auto &best = *SDL_GetVideoInfo(); @@ -116,17 +123,17 @@ bool SpawnWindow(const char *lpWindowName, int nWidth, int nHeight) #ifdef USE_SDL1 SDL_Log("upscaling not supported with USE_SDL1"); #else - renderer = SDL_CreateRenderer(ghMainWnd, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); + renderer = SDL_CreateRenderer(ghMainWnd, -1, /*SDL_RENDERER_PRESENTVSYNC |*/ SDL_RENDERER_ACCELERATED); /*no vsync for fps testing*/ if (renderer == NULL) { ErrSdl(); } - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, nWidth, nHeight); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, /*nWidth*/1280, /*nHeight*/960); if (texture == NULL) { ErrSdl(); } - if (SDL_RenderSetLogicalSize(renderer, nWidth, nHeight) <= -1) { + if (SDL_RenderSetLogicalSize(renderer, /*nWidth*/1280, /*nHeight*/960) <= -1) { ErrSdl(); } #endif diff --git a/SourceX/dx.cpp b/SourceX/dx.cpp index c8bb73840..1944f1288 100644 --- a/SourceX/dx.cpp +++ b/SourceX/dx.cpp @@ -7,6 +7,10 @@ #include "../3rdParty/Storm/Source/storm.h" #include "display.h" #include +#include "filters/xbrz/xbrz.h" // header needed for xrbz +#include // header needed for multithreading + +extern int processors; /* defined in display.cpp */ namespace dvl { @@ -28,13 +32,88 @@ unsigned int pal_surface_palette_version = 0; /** 24-bit renderer texture surface */ SDL_Surface *renderer_texture_surface = nullptr; - +SDL_Surface *scale_renderer_texture_surface = nullptr; /* renderer texture surface for scaled picture */ /** 8-bit surface wrapper around #gpBuffer */ SDL_Surface *pal_surface; /** To know if surfaces have been initialized or not */ BOOL was_window_init = false; +/* definitions, functions needed for multithreading and xbrz */ +#define TASKS 480 /* maximum number of simultaneous tasks. In this case 480 lines of a picture */ + +int num_threads; + +struct thread_info +{ + int id; + pthread_t thread; + unsigned int *unscaled_picture; + unsigned int *scale_pixels; + unsigned int *pixels; +}; + +static void *thread_function(void *arg) +{ + struct thread_info *thread = (struct thread_info *)arg; + + int yFirst; + int yLast; + + yFirst = (480/num_threads)*thread->id; + yLast = (480/num_threads)*thread->id+(480/num_threads); + + /*prepare unscaled copy of picture for applying xbrz*/ + for(int y=yFirst; yunscaled_picture[y*640], &thread->pixels[y*640*2], 640*4); + /*prepare unscaled copy of picture for applying xbrz*/ + + /*apply xbrz*/ + xbrz::scale(2, thread->unscaled_picture, thread->scale_pixels, 640, 480, xbrz::ColorFormat::RGB, xbrz::ScalerCfg(), yFirst, yLast); + /*apply xbrz*/ + + return NULL; +} + +int run_threads(int tasks, unsigned int *unscaled_picture, unsigned int *scale_pixels, unsigned int *pixels) +{ + int i; + + if(tasks < processors) + num_threads = tasks; + else + num_threads = processors; + + struct thread_info *mythreads = (struct thread_info*)malloc(sizeof(struct thread_info) * num_threads); + //struct thread_info *mythreads = malloc(sizeof(struct thread_info) * num_threads); + + for(i = 0; i < num_threads; i++) + { + mythreads[i].id = i; + mythreads[i].unscaled_picture = unscaled_picture; + mythreads[i].scale_pixels = scale_pixels; + mythreads[i].pixels = pixels; + + if(pthread_create(&mythreads[i].thread, NULL, thread_function, (void *) &mythreads[i])) + { + printf("ERROR in pthread_create %d\n", i); + return 1; + } + } + + for(i = 0; i < num_threads; i++) + { + if(pthread_join(mythreads[i].thread, NULL)) + { + printf("ERROR in pthread_join %d\n", i); + return 1; + } + } + + free(mythreads); + return 0; +} +/* definitions, functions needed for multithreading and xbrz */ + static void dx_create_back_buffer() { pal_surface = SDL_CreateRGBSurfaceWithFormat(0, BUFFER_WIDTH, BUFFER_HEIGHT, 8, SDL_PIXELFORMAT_INDEX8); @@ -66,7 +145,8 @@ static void dx_create_primary_surface() Uint32 format; if (SDL_QueryTexture(texture, &format, nullptr, nullptr, nullptr) < 0) ErrSdl(); - renderer_texture_surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, SDL_BITSPERPIXEL(format), format); + renderer_texture_surface = SDL_CreateRGBSurfaceWithFormat(0, /*width*/1280, /*height*/960, SDL_BITSPERPIXEL(format), format); // increase buffer size by 2x + scale_renderer_texture_surface = SDL_CreateRGBSurfaceWithFormat(0, 1280, 960, SDL_BITSPERPIXEL(format), format); // create surface for filter } #endif if (GetOutputSurface() == nullptr) { @@ -143,6 +223,7 @@ void dx_cleanup() pal_surface = nullptr; SDL_FreePalette(palette); SDL_FreeSurface(renderer_texture_surface); + SDL_FreeSurface(scale_renderer_texture_surface); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(ghMainWnd); @@ -255,6 +336,20 @@ void LimitFrameRate() void RenderPresent() { SDL_Surface *surface = GetOutputSurface(); + + /*scaling operation start*/ + unsigned int *pixels = (unsigned int*)renderer_texture_surface->pixels; /* source picture. left top position. */ + unsigned int *scale_pixels = (unsigned int*)scale_renderer_texture_surface->pixels; /* destination buffer for scaled picture */ + unsigned int *unscaled_picture = (unsigned int*)malloc(640*480*4); /* buffer for copy of unscaled picture */ + + run_threads(TASKS, unscaled_picture, scale_pixels, pixels); /*apply multithreaded xbrz filter*/ + + /* copy back the scaled surface to renderer_texture_surface */ + memcpy(pixels, scale_pixels, sizeof(*pixels)*640*480*2*2); + /* copy back the scaled surface to renderer_texture_surface */ + free(unscaled_picture); + /*scaling operation end*/ + assert(!SDL_MUSTLOCK(surface)); if (!gbActive) { diff --git a/SourceX/filters/xbrz/Changelog.txt b/SourceX/filters/xbrz/Changelog.txt new file mode 100644 index 000000000..4526b86b7 --- /dev/null +++ b/SourceX/filters/xbrz/Changelog.txt @@ -0,0 +1,66 @@ +xBRZ 1.8 [2019-11-28] +--------------------- +Consider ARGB outside area as transparent +Fixed ARGB scaling issue on image borders + + +xBRZ 1.7 [2019-07-04] +--------------------- +Fixed asymmetric color distance +New parameter: "Center direction bias" + + +xBRZ 1.6 [2018-02-27] +--------------------- +Added bilinear scaling +Option to skip color buffer creation +Updated license info + + +xBRZ 1.5 [2017-08-07] +--------------------- +Added RGB conversion routines + + +xBRZ 1.4 [2015-07-25] +--------------------- +Added 6xBRZ scaler +Create color distance buffer lazily + + +xBRZ 1.3 [2015-04-03] +--------------------- +Improved ARGB performance by 15% +Fixed alpha channel gradient bug + + +xBRZ 1.2 [2014-11-21] +--------------------- +Further improved performance by over 30% + + +xBRZ 1.1 [2014-11-02] +--------------------- +Support images with alpha channel +Improved color analysis + + +xBRZ 1.0 [2013-02-11] +--------------------- +Fixed xBRZ scaler compiler issues for GCC + + +xBRZ 0.2 [2012-12-11] +--------------------- +Added 5xBRZ scaler +Optimized xBRZ scaler performance by factor 3 +Further improved image quality of xBRZ scaler + + +xBRZ 0.1 [2012-09-26] +--------------------- +Initial release: +- scale while preserving small image features +- support multithreading +- support 64-bit architectures +- support processing image slices diff --git a/SourceX/filters/xbrz/License.txt b/SourceX/filters/xbrz/License.txt new file mode 100644 index 000000000..7c0565127 --- /dev/null +++ b/SourceX/filters/xbrz/License.txt @@ -0,0 +1,622 @@ + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS diff --git a/SourceX/filters/xbrz/xbrz.cpp b/SourceX/filters/xbrz/xbrz.cpp new file mode 100644 index 000000000..c14eeb1e1 --- /dev/null +++ b/SourceX/filters/xbrz/xbrz.cpp @@ -0,0 +1,1363 @@ +// **************************************************************************** +// * This file is part of the xBRZ project. It is distributed under * +// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * +// * * +// * Additionally and as a special exception, the author gives permission * +// * to link the code of this program with the following libraries * +// * (or with modified versions that use the same licenses), and distribute * +// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe * +// * You must obey the GNU General Public License in all respects for all of * +// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. * +// * If you modify this file, you may extend this exception to your version * +// * of the file, but you are not obligated to do so. If you do not wish to * +// * do so, delete this exception statement from your version. * +// **************************************************************************** + +#include "xbrz.h" +#include +#include +#include +#include //std::sqrt +#include "xbrz_tools.h" + +using namespace xbrz; + +static int clamp(int x, int lower, int upper) +{ + return std::min(upper, std::max(x, lower)); +} + +namespace +{ + + + +template inline +uint32_t gradientRGB(uint32_t pixFront, uint32_t pixBack) //blend front color with opacity M / N over opaque background: https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending +{ + static_assert(0 < M && M < N && N <= 1000); + + auto calcColor = [](unsigned char colFront, unsigned char colBack) -> unsigned char { return (colFront * M + colBack * (N - M)) / N; }; + + return makePixel(calcColor(getRed (pixFront), getRed (pixBack)), + calcColor(getGreen(pixFront), getGreen(pixBack)), + calcColor(getBlue (pixFront), getBlue (pixBack))); +} + + +template inline +uint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) //find intermediate color between two colors with alpha channels (=> NO alpha blending!!!) +{ + static_assert(0 < M && M < N && N <= 1000); + + const unsigned int weightFront = getAlpha(pixFront) * M; + const unsigned int weightBack = getAlpha(pixBack) * (N - M); + const unsigned int weightSum = weightFront + weightBack; + if (weightSum == 0) + return 0; + + auto calcColor = [=](unsigned char colFront, unsigned char colBack) + { + return static_cast((colFront * weightFront + colBack * weightBack) / weightSum); + }; + + return makePixel(static_cast(weightSum / N), + calcColor(getRed (pixFront), getRed (pixBack)), + calcColor(getGreen(pixFront), getGreen(pixBack)), + calcColor(getBlue (pixFront), getBlue (pixBack))); +} + + +//inline +//double fastSqrt(double n) +//{ +// __asm //speeds up xBRZ by about 9% compared to std::sqrt which internally uses the same assembler instructions but adds some "fluff" +// { +// fld n +// fsqrt +// } +//} +// + + +#ifdef _MSC_VER + #define FORCE_INLINE __forceinline +#elif defined __GNUC__ + #define FORCE_INLINE __attribute__((always_inline)) inline +#else + #define FORCE_INLINE inline +#endif + + +enum RotationDegree //clock-wise +{ + ROT_0, + ROT_90, + ROT_180, + ROT_270 +}; + +//calculate input matrix coordinates after rotation at compile time +template +struct MatrixRotation; + +template +struct MatrixRotation +{ + static const size_t I_old = I; + static const size_t J_old = J; +}; + +template //(i, j) = (row, col) indices, N = size of (square) matrix +struct MatrixRotation +{ + static const size_t I_old = N - 1 - MatrixRotation(rotDeg - 1), I, J, N>::J_old; //old coordinates before rotation! + static const size_t J_old = MatrixRotation(rotDeg - 1), I, J, N>::I_old; // +}; + + +template +class OutputMatrix +{ +public: + OutputMatrix(uint32_t* out, int outWidth) : //access matrix area, top-left at position "out" for image with given width + out_(out), + outWidth_(outWidth) {} + + template + uint32_t& ref() const + { + static const size_t I_old = MatrixRotation::I_old; + static const size_t J_old = MatrixRotation::J_old; + return *(out_ + J_old + I_old * outWidth_); + } + +private: + uint32_t* out_; + const int outWidth_; +}; + + +template inline +T square(T value) { return value * value; } + + +#if 0 +inline +double distRGB(uint32_t pix1, uint32_t pix2) +{ + const double r_diff = static_cast(getRed (pix1)) - getRed (pix2); + const double g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); + const double b_diff = static_cast(getBlue (pix1)) - getBlue (pix2); + + //euklidean RGB distance + return std::sqrt(square(r_diff) + square(g_diff) + square(b_diff)); +} +#endif + + +inline +double distYCbCr(uint32_t pix1, uint32_t pix2, double lumaWeight) +{ + //https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion + //YCbCr conversion is a matrix multiplication => take advantage of linearity by subtracting first! + const int r_diff = static_cast(getRed (pix1)) - getRed (pix2); //we may delay division by 255 to after matrix multiplication + const int g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); // + const int b_diff = static_cast(getBlue (pix1)) - getBlue (pix2); //substraction for int is noticeable faster than for double! + + //const double k_b = 0.0722; //ITU-R BT.709 conversion + //const double k_r = 0.2126; // + const double k_b = 0.0593; //ITU-R BT.2020 conversion + const double k_r = 0.2627; // + const double k_g = 1 - k_b - k_r; + + const double scale_b = 0.5 / (1 - k_b); + const double scale_r = 0.5 / (1 - k_r); + + const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr! + const double c_b = scale_b * (b_diff - y); + const double c_r = scale_r * (r_diff - y); + + //we skip division by 255 to have similar range like other distance functions + return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)); +} + + +inline +double distYCbCrBuffered(uint32_t pix1, uint32_t pix2) +{ + //30% perf boost compared to plain distYCbCr()! + //consumes 64 MB memory; using double is only 2% faster, but takes 128 MB + static const std::vector diffToDist = [] + { + std::vector tmp; + + for (uint32_t i = 0; i < 256 * 256 * 256; ++i) //startup time: 114 ms on Intel Core i5 (four cores) + { + const int r_diff = static_cast(getByte<2>(i)) * 2; + const int g_diff = static_cast(getByte<1>(i)) * 2; + const int b_diff = static_cast(getByte<0>(i)) * 2; + + const double k_b = 0.0593; //ITU-R BT.2020 conversion + const double k_r = 0.2627; // + const double k_g = 1 - k_b - k_r; + + const double scale_b = 0.5 / (1 - k_b); + const double scale_r = 0.5 / (1 - k_r); + + const double y = k_r * r_diff + k_g * g_diff + k_b * b_diff; //[!], analog YCbCr! + const double c_b = scale_b * (b_diff - y); + const double c_r = scale_r * (r_diff - y); + + tmp.push_back(static_cast(std::sqrt(square(y) + square(c_b) + square(c_r)))); + } + return tmp; + }(); + + //if (pix1 == pix2) -> 8% perf degradation! + // return 0; + //if (pix1 < pix2) + // std::swap(pix1, pix2); -> 30% perf degradation!!! + + const int r_diff = static_cast(getRed (pix1)) - getRed (pix2); + const int g_diff = static_cast(getGreen(pix1)) - getGreen(pix2); + const int b_diff = static_cast(getBlue (pix1)) - getBlue (pix2); + + const size_t index = (static_cast(r_diff / 2) << 16) | //slightly reduce precision (division by 2) to squeeze value into single byte + (static_cast(g_diff / 2) << 8) | + (static_cast(b_diff / 2)); + +#if 0 //attention: the following calculation creates an asymmetric color distance!!! (e.g. r_diff=46 will be unpacked as 45, but r_diff=-46 unpacks to -47 + const size_t index = (((r_diff + 0xFF) / 2) << 16) | //slightly reduce precision (division by 2) to squeeze value into single byte + (((g_diff + 0xFF) / 2) << 8) | + (( b_diff + 0xFF) / 2); +#endif + return diffToDist[index]; +} + + +#if defined _MSC_VER && !defined NDEBUG + const int debugPixelX = -1; + const int debugPixelY = 58; + + thread_local bool breakIntoDebugger = false; +#endif + + +enum BlendType +{ + BLEND_NONE = 0, + BLEND_NORMAL, //a normal indication to blend + BLEND_DOMINANT, //a strong indication to blend + //attention: BlendType must fit into the value range of 2 bit!!! +}; + +struct BlendResult +{ + BlendType + /**/blend_f, blend_g, + /**/blend_j, blend_k; +}; + + +struct Kernel_3x3 +{ + uint32_t + a, b, c, + d, e, f, + g, h, i; +}; + +struct Kernel_4x4 //kernel for preprocessing step +{ + uint32_t + a, b, c, // + e, f, g, // support reinterpret_cast from Kernel_4x4 => Kernel_3x3 + i, j, k, // + m, n, o, + d, h, l, p; +}; + +/* input kernel area naming convention: +----------------- +| A | B | C | D | +|---|---|---|---| +| E | F | G | H | evaluate the four corners between F, G, J, K +|---|---|---|---| input pixel is at position F +| I | J | K | L | +|---|---|---|---| +| M | N | O | P | +----------------- +*/ +template +FORCE_INLINE //detect blend direction +BlendResult preProcessCorners(const Kernel_4x4& ker, const xbrz::ScalerCfg& cfg) //result: F, G, J, K corners of "GradientType" +{ +#if defined _MSC_VER && !defined NDEBUG + if (breakIntoDebugger) + __debugbreak(); //__asm int 3; +#endif + + BlendResult result = {}; + + if ((ker.f == ker.g && + ker.j == ker.k) || + (ker.f == ker.j && + ker.g == ker.k)) + return result; + + auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; + + double jg = dist(ker.i, ker.f) + dist(ker.f, ker.c) + dist(ker.n, ker.k) + dist(ker.k, ker.h) + cfg.centerDirectionBias * dist(ker.j, ker.g); + double fk = dist(ker.e, ker.j) + dist(ker.j, ker.o) + dist(ker.b, ker.g) + dist(ker.g, ker.l) + cfg.centerDirectionBias * dist(ker.f, ker.k); + + if (jg < fk) //test sample: 70% of values max(jg, fk) / min(jg, fk) are between 1.1 and 3.7 with median being 1.8 + { + const bool dominantGradient = cfg.dominantDirectionThreshold * jg < fk; + if (ker.f != ker.g && ker.f != ker.j) + result.blend_f = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + + if (ker.k != ker.j && ker.k != ker.g) + result.blend_k = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + } + else if (fk < jg) + { + const bool dominantGradient = cfg.dominantDirectionThreshold * fk < jg; + if (ker.j != ker.f && ker.j != ker.k) + result.blend_j = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + + if (ker.g != ker.f && ker.g != ker.k) + result.blend_g = dominantGradient ? BLEND_DOMINANT : BLEND_NORMAL; + } + return result; +} + +#define DEF_GETTER(x) template uint32_t inline get_##x(const Kernel_3x3& ker) { return ker.x; } +//we cannot and NEED NOT write "ker.##x" since ## concatenates preprocessor tokens but "." is not a token +DEF_GETTER(a) DEF_GETTER(b) DEF_GETTER(c) +DEF_GETTER(d) DEF_GETTER(e) DEF_GETTER(f) +DEF_GETTER(g) DEF_GETTER(h) DEF_GETTER(i) +#undef DEF_GETTER + +#define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } +DEF_GETTER(a, g) DEF_GETTER(b, d) DEF_GETTER(c, a) +DEF_GETTER(d, h) DEF_GETTER(e, e) DEF_GETTER(f, b) +DEF_GETTER(g, i) DEF_GETTER(h, f) DEF_GETTER(i, c) +#undef DEF_GETTER + +#define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } +DEF_GETTER(a, i) DEF_GETTER(b, h) DEF_GETTER(c, g) +DEF_GETTER(d, f) DEF_GETTER(e, e) DEF_GETTER(f, d) +DEF_GETTER(g, c) DEF_GETTER(h, b) DEF_GETTER(i, a) +#undef DEF_GETTER + +#define DEF_GETTER(x, y) template <> inline uint32_t get_##x(const Kernel_3x3& ker) { return ker.y; } +DEF_GETTER(a, c) DEF_GETTER(b, f) DEF_GETTER(c, i) +DEF_GETTER(d, b) DEF_GETTER(e, e) DEF_GETTER(f, h) +DEF_GETTER(g, a) DEF_GETTER(h, d) DEF_GETTER(i, g) +#undef DEF_GETTER + + +//compress four blend types into a single byte +//inline BlendType getTopL (unsigned char b) { return static_cast(0x3 & b); } +inline BlendType getTopR (unsigned char b) { return static_cast(0x3 & (b >> 2)); } +inline BlendType getBottomR(unsigned char b) { return static_cast(0x3 & (b >> 4)); } +inline BlendType getBottomL(unsigned char b) { return static_cast(0x3 & (b >> 6)); } + +inline void clearAddTopL(unsigned char& b, BlendType bt) { b = static_cast(bt); } +inline void addTopR (unsigned char& b, BlendType bt) { b |= (bt << 2); } //buffer is assumed to be initialized before preprocessing! +inline void addBottomR (unsigned char& b, BlendType bt) { b |= (bt << 4); } //e.g. via clearAddTopL() +inline void addBottomL (unsigned char& b, BlendType bt) { b |= (bt << 6); } // + +inline bool blendingNeeded(unsigned char b) +{ + static_assert(BLEND_NONE == 0); + return b != 0; +} + +template inline +unsigned char rotateBlendInfo(unsigned char b) { return b; } +template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 2) | (b >> 6)) & 0xff; } +template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 4) | (b >> 4)) & 0xff; } +template <> inline unsigned char rotateBlendInfo(unsigned char b) { return ((b << 6) | (b >> 2)) & 0xff; } + + +/* input kernel area naming convention: +------------- +| A | B | C | +|---|---|---| +| D | E | F | input pixel is at position E +|---|---|---| +| G | H | I | +------------- +*/ +template +FORCE_INLINE //perf: quite worth it! +void blendPixel(const Kernel_3x3& ker, + uint32_t* target, int trgWidth, + unsigned char blendInfo, //result of preprocessing all four corners of pixel "e" + const xbrz::ScalerCfg& cfg) +{ + //#define a get_a(ker) +#define b get_b(ker) +#define c get_c(ker) +#define d get_d(ker) +#define e get_e(ker) +#define f get_f(ker) +#define g get_g(ker) +#define h get_h(ker) +#define i get_i(ker) + +#if defined _MSC_VER && !defined NDEBUG + if (breakIntoDebugger) + __debugbreak(); //__asm int 3; +#endif + + const unsigned char blend = rotateBlendInfo(blendInfo); + + if (getBottomR(blend) >= BLEND_NORMAL) + { + auto eq = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight) < cfg.equalColorTolerance; }; + auto dist = [&](uint32_t pix1, uint32_t pix2) { return ColorDistance::dist(pix1, pix2, cfg.luminanceWeight); }; + + const bool doLineBlend = [&]() -> bool + { + if (getBottomR(blend) >= BLEND_DOMINANT) + return true; + + //make sure there is no second blending in an adjacent rotation for this pixel: handles insular pixels, mario eyes + if (getTopR(blend) != BLEND_NONE && !eq(e, g)) //but support double-blending for 90 corners + return false; + if (getBottomL(blend) != BLEND_NONE && !eq(e, c)) + return false; + + //no full blending for L-shapes; blend corner only (handles "mario mushroom eyes") + if (!eq(e, i) && eq(g, h) && eq(h, i) && eq(i, f) && eq(f, c)) + return false; + + return true; + }(); + + const uint32_t px = dist(e, f) <= dist(e, h) ? f : h; //choose most similar color + + OutputMatrix out(target, trgWidth); + + if (doLineBlend) + { + const double fg = dist(f, g); //test sample: 70% of values max(fg, hc) / min(fg, hc) are between 1.1 and 3.7 with median being 1.9 + const double hc = dist(h, c); // + + const bool haveShallowLine = cfg.steepDirectionThreshold * fg <= hc && e != g && d != g; + const bool haveSteepLine = cfg.steepDirectionThreshold * hc <= fg && e != c && b != c; + + if (haveShallowLine) + { + if (haveSteepLine) + Scaler::blendLineSteepAndShallow(px, out); + else + Scaler::blendLineShallow(px, out); + } + else + { + if (haveSteepLine) + Scaler::blendLineSteep(px, out); + else + Scaler::blendLineDiagonal(px, out); + } + } + else + Scaler::blendCorner(px, out); + } + + //#undef a +#undef b +#undef c +#undef d +#undef e +#undef f +#undef g +#undef h +#undef i +} + + +class OobReaderTransparent +{ +public: + OobReaderTransparent(const uint32_t* src, int srcWidth, int srcHeight, int y) : + s_m1(0 <= y - 1 && y - 1 < srcHeight ? src + srcWidth * (y - 1) : nullptr), + s_0 (0 <= y && y < srcHeight ? src + srcWidth * y : nullptr), + s_p1(0 <= y + 1 && y + 1 < srcHeight ? src + srcWidth * (y + 1) : nullptr), + s_p2(0 <= y + 2 && y + 2 < srcHeight ? src + srcWidth * (y + 2) : nullptr), + srcWidth_(srcWidth) {} + + void readDhlp(Kernel_4x4& ker, int x) const //(x, y) is at kernel position F + { + [[likely]] if (const int x_p2 = x + 2; 0 <= x_p2 && x_p2 < srcWidth_) + { + ker.d = s_m1 ? s_m1[x_p2] : 0; + ker.h = s_0 ? s_0 [x_p2] : 0; + ker.l = s_p1 ? s_p1[x_p2] : 0; + ker.p = s_p2 ? s_p2[x_p2] : 0; + } + else + { + ker.d = 0; + ker.h = 0; + ker.l = 0; + ker.p = 0; + } + } + +private: + const uint32_t* const s_m1; + const uint32_t* const s_0; + const uint32_t* const s_p1; + const uint32_t* const s_p2; + const int srcWidth_; +}; + + +class OobReaderDuplicate +{ +public: + OobReaderDuplicate(const uint32_t* src, int srcWidth, int srcHeight, int y) : + s_m1(src + srcWidth * clamp(y - 1, 0, srcHeight - 1)), + s_0 (src + srcWidth * clamp(y, 0, srcHeight - 1)), + s_p1(src + srcWidth * clamp(y + 1, 0, srcHeight - 1)), + s_p2(src + srcWidth * clamp(y + 2, 0, srcHeight - 1)), + srcWidth_(srcWidth) {} + + void readDhlp(Kernel_4x4& ker, int x) const //(x, y) is at kernel position F + { + const int x_p2 = clamp(x + 2, 0, srcWidth_ - 1); + ker.d = s_m1[x_p2]; + ker.h = s_0 [x_p2]; + ker.l = s_p1[x_p2]; + ker.p = s_p2[x_p2]; + } + +private: + const uint32_t* const s_m1; + const uint32_t* const s_0; + const uint32_t* const s_p1; + const uint32_t* const s_p2; + const int srcWidth_; +}; + + +template //scaler policy: see "Scaler2x" reference implementation +void scaleImage(const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) +{ + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, srcHeight); + if (yFirst >= yLast || srcWidth <= 0) + return; + + const int trgWidth = srcWidth * Scaler::scale; + + //(ab)use space of "sizeof(uint32_t) * srcWidth * Scaler::scale" at the end of the image as temporary + //buffer for "on the fly preprocessing" without risk of accidental overwriting before accessing + unsigned char* const preProcBuf = reinterpret_cast(trg + yLast * Scaler::scale * trgWidth) - srcWidth; + + //initialize preprocessing buffer for first row of current stripe: detect upper left and right corner blending + //this cannot be optimized for adjacent processing stripes; we must not allow for a memory race condition! + { + const OobReader oobReader(src, srcWidth, srcHeight, yFirst - 1); + + //initialize at position x = -1 + Kernel_4x4 ker4 = {}; + oobReader.readDhlp(ker4, -4); //hack: read a, e, i, m at x = -1 + ker4.a = ker4.d; + ker4.e = ker4.h; + ker4.i = ker4.l; + ker4.m = ker4.p; + + oobReader.readDhlp(ker4, -3); + ker4.b = ker4.d; + ker4.f = ker4.h; + ker4.j = ker4.l; + ker4.n = ker4.p; + + oobReader.readDhlp(ker4, -2); + ker4.c = ker4.d; + ker4.g = ker4.h; + ker4.k = ker4.l; + ker4.o = ker4.p; + + oobReader.readDhlp(ker4, -1); + + { + const BlendResult res = preProcessCorners(ker4, cfg); + clearAddTopL(preProcBuf[0], res.blend_k); //set 1st known corner for (0, yFirst) + } + + for (int x = 0; x < srcWidth; ++x) + { + ker4.a = ker4.b; //shift previous kernel to the left + ker4.e = ker4.f; // ----------------- + ker4.i = ker4.j; // | A | B | C | D | + ker4.m = ker4.n; // |---|---|---|---| + /**/ // | E | F | G | H | (x, yFirst - 1) is at position F + ker4.b = ker4.c; // |---|---|---|---| + ker4.f = ker4.g; // | I | J | K | L | + ker4.j = ker4.k; // |---|---|---|---| + ker4.n = ker4.o; // | M | N | O | P | + /**/ // ----------------- + ker4.c = ker4.d; + ker4.g = ker4.h; + ker4.k = ker4.l; + ker4.o = ker4.p; + + oobReader.readDhlp(ker4, x); + + /* preprocessing blend result: + --------- + | F | G | evaluate corner between F, G, J, K + |---+---| current input pixel is at position F + | J | K | + --------- */ + const BlendResult res = preProcessCorners(ker4, cfg); + addTopR(preProcBuf[x], res.blend_j); //set 2nd known corner for (x, yFirst) + + if (x + 1 < srcWidth) + clearAddTopL(preProcBuf[x + 1], res.blend_k); //set 1st known corner for (x + 1, yFirst) + } + } + //------------------------------------------------------------------------------------ + + for (int y = yFirst; y < yLast; ++y) + { + uint32_t* out = trg + Scaler::scale * y * trgWidth; //consider MT "striped" access + + const OobReader oobReader(src, srcWidth, srcHeight, y); + + //initialize at position x = -1 + Kernel_4x4 ker4 = {}; + oobReader.readDhlp(ker4, -4); //hack: read a, e, i, m at x = -1 + ker4.a = ker4.d; + ker4.e = ker4.h; + ker4.i = ker4.l; + ker4.m = ker4.p; + + oobReader.readDhlp(ker4, -3); + ker4.b = ker4.d; + ker4.f = ker4.h; + ker4.j = ker4.l; + ker4.n = ker4.p; + + oobReader.readDhlp(ker4, -2); + ker4.c = ker4.d; + ker4.g = ker4.h; + ker4.k = ker4.l; + ker4.o = ker4.p; + + oobReader.readDhlp(ker4, -1); + + unsigned char blend_xy1 = 0; //corner blending for current (x, y + 1) position + { + const BlendResult res = preProcessCorners(ker4, cfg); + clearAddTopL(blend_xy1, res.blend_k); //set 1st known corner for (0, y + 1) and buffer for use on next column + + addBottomL(preProcBuf[0], res.blend_g); //set 3rd known corner for (0, y) + } + + for (int x = 0; x < srcWidth; ++x, out += Scaler::scale) + { +#if defined _MSC_VER && !defined NDEBUG + breakIntoDebugger = debugPixelX == x && debugPixelY == y; +#endif + ker4.a = ker4.b; //shift previous kernel to the left + ker4.e = ker4.f; // ----------------- + ker4.i = ker4.j; // | A | B | C | D | + ker4.m = ker4.n; // |---|---|---|---| + /**/ // | E | F | G | H | (x, y) is at position F + ker4.b = ker4.c; // |---|---|---|---| + ker4.f = ker4.g; // | I | J | K | L | + ker4.j = ker4.k; // |---|---|---|---| + ker4.n = ker4.o; // | M | N | O | P | + /**/ // ----------------- + ker4.c = ker4.d; + ker4.g = ker4.h; + ker4.k = ker4.l; + ker4.o = ker4.p; + + oobReader.readDhlp(ker4, x); + + //evaluate the four corners on bottom-right of current pixel + unsigned char blend_xy = preProcBuf[x]; //for current (x, y) position + { + /* preprocessing blend result: + --------- + | F | G | evaluate corner between F, G, J, K + |---+---| current input pixel is at position F + | J | K | + --------- */ + const BlendResult res = preProcessCorners(ker4, cfg); + addBottomR(blend_xy, res.blend_f); //all four corners of (x, y) have been determined at this point due to processing sequence! + + addTopR(blend_xy1, res.blend_j); //set 2nd known corner for (x, y + 1) + preProcBuf[x] = blend_xy1; //store on current buffer position for use on next row + + [[likely]] if (x + 1 < srcWidth) + { + //blend_xy1 -> blend_x1y1 + clearAddTopL(blend_xy1, res.blend_k); //set 1st known corner for (x + 1, y + 1) and buffer for use on next column + + addBottomL(preProcBuf[x + 1], res.blend_g); //set 3rd known corner for (x + 1, y) + } + } + + //fill block of size scale * scale with the given color + fillBlock(out, trgWidth * sizeof(uint32_t), ker4.f, Scaler::scale, Scaler::scale); + //place *after* preprocessing step, to not overwrite the results while processing the last pixel! + + //blend all four corners of current pixel + if (blendingNeeded(blend_xy)) + { + const auto& ker3 = reinterpret_cast(ker4); //"The Things We Do for Perf" + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + blendPixel(ker3, out, trgWidth, blend_xy, cfg); + } + } + } +} + +//------------------------------------------------------------------------------------ + +template +struct Scaler2x : public ColorGradient +{ + static const int scale = 2; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<1, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 1>(), col); + alphaGrad<5, 6>(out.template ref<1, 1>(), col); //[!] fixes 7/8 used in xBR + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref<1, 1>(), col); + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<21, 100>(out.template ref<1, 1>(), col); //exact: 1 - pi/4 = 0.2146018366 + } +}; + + +template +struct Scaler3x : public ColorGradient +{ + static const int scale = 3; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + out.template ref<2, scale - 1>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<2, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 2>(), col); + alphaGrad<3, 4>(out.template ref<2, 1>(), col); + alphaGrad<3, 4>(out.template ref<1, 2>(), col); + out.template ref<2, 2>() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 8>(out.template ref<1, 2>(), col); //conflict with other rotations for this odd scale + alphaGrad<1, 8>(out.template ref<2, 1>(), col); + alphaGrad<7, 8>(out.template ref<2, 2>(), col); // + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<45, 100>(out.template ref<2, 2>(), col); //exact: 0.4545939598 + //alphaGrad<7, 256>(out.template ref<2, 1>(), col); //0.02826017254 -> negligible + avoid conflicts with other rotations for this odd scale + //alphaGrad<7, 256>(out.template ref<1, 2>(), col); //0.02826017254 + } +}; + + +template +struct Scaler4x : public ColorGradient +{ + static const int scale = 4; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<3, 4>(out.template ref<3, 1>(), col); + alphaGrad<3, 4>(out.template ref<1, 3>(), col); + alphaGrad<1, 4>(out.template ref<3, 0>(), col); + alphaGrad<1, 4>(out.template ref<0, 3>(), col); + + alphaGrad<1, 3>(out.template ref<2, 2>(), col); //[!] fixes 1/4 used in xBR + + out.template ref<3, 3>() = col; + out.template ref<3, 2>() = col; + out.template ref<2, 3>() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + out.template ref() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<68, 100>(out.template ref<3, 3>(), col); //exact: 0.6848532563 + alphaGrad< 9, 100>(out.template ref<3, 2>(), col); //0.08677704501 + alphaGrad< 9, 100>(out.template ref<2, 3>(), col); //0.08677704501 + } +}; + + +template +struct Scaler5x : public ColorGradient +{ + static const int scale = 5; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<4, scale - 2>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + alphaGrad<2, 3>(out.template ref<3, 3>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 8>(out.template ref(), col); //conflict with other rotations for this odd scale + alphaGrad<1, 8>(out.template ref(), col); + alphaGrad<1, 8>(out.template ref(), col); // + + alphaGrad<7, 8>(out.template ref<4, 3>(), col); + alphaGrad<7, 8>(out.template ref<3, 4>(), col); + + out.template ref<4, 4>() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<86, 100>(out.template ref<4, 4>(), col); //exact: 0.8631434088 + alphaGrad<23, 100>(out.template ref<4, 3>(), col); //0.2306749731 + alphaGrad<23, 100>(out.template ref<3, 4>(), col); //0.2306749731 + //alphaGrad<1, 64>(out.template ref<4, 2>(), col); //0.01676812367 -> negligible + avoid conflicts with other rotations for this odd scale + //alphaGrad<1, 64>(out.template ref<2, 4>(), col); //0.01676812367 + } +}; + + +template +struct Scaler6x : public ColorGradient +{ + static const int scale = 6; + + template //bring template function into scope for GCC + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) { ColorGradient::template alphaGrad(pixBack, pixFront); } + + + template + static void blendLineShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineSteep(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<1, 4>(out.template ref<4, scale - 3>(), col); + + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<5, scale - 3>(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<5, scale - 1>() = col; + + out.template ref<4, scale - 2>() = col; + out.template ref<5, scale - 2>() = col; + } + + template + static void blendLineSteepAndShallow(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 4>(out.template ref<0, scale - 1>(), col); + alphaGrad<1, 4>(out.template ref<2, scale - 2>(), col); + alphaGrad<3, 4>(out.template ref<1, scale - 1>(), col); + alphaGrad<3, 4>(out.template ref<3, scale - 2>(), col); + + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<1, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + alphaGrad<3, 4>(out.template ref(), col); + + out.template ref<2, scale - 1>() = col; + out.template ref<3, scale - 1>() = col; + out.template ref<4, scale - 1>() = col; + out.template ref<5, scale - 1>() = col; + + out.template ref<4, scale - 2>() = col; + out.template ref<5, scale - 2>() = col; + + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendLineDiagonal(uint32_t col, OutputMatrix& out) + { + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + alphaGrad<1, 2>(out.template ref(), col); + + out.template ref() = col; + out.template ref() = col; + out.template ref() = col; + } + + template + static void blendCorner(uint32_t col, OutputMatrix& out) + { + //model a round corner + alphaGrad<97, 100>(out.template ref<5, 5>(), col); //exact: 0.9711013910 + alphaGrad<42, 100>(out.template ref<4, 5>(), col); //0.4236372243 + alphaGrad<42, 100>(out.template ref<5, 4>(), col); //0.4236372243 + alphaGrad< 6, 100>(out.template ref<5, 3>(), col); //0.05652034508 + alphaGrad< 6, 100>(out.template ref<3, 5>(), col); //0.05652034508 + } +}; + +//------------------------------------------------------------------------------------ + +struct ColorDistanceRGB +{ + static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) + { + return distYCbCrBuffered(pix1, pix2); + + //if (pix1 == pix2) //about 4% perf boost + // return 0; + //return distYCbCr(pix1, pix2, luminanceWeight); + } +}; + +struct ColorDistanceARGB +{ + static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) + { + const double a1 = getAlpha(pix1) / 255.0 ; + const double a2 = getAlpha(pix2) / 255.0 ; + /* + Requirements for a color distance handling alpha channel: with a1, a2 in [0, 1] + + 1. if a1 = a2, distance should be: a1 * distYCbCr() + 2. if a1 = 0, distance should be: a2 * distYCbCr(black, white) = a2 * 255 + 3. if a1 = 1, ??? maybe: 255 * (1 - a2) + a2 * distYCbCr() + */ + + //return std::min(a1, a2) * distYCbCrBuffered(pix1, pix2) + 255 * abs(a1 - a2); + //=> following code is 15% faster: + const double d = distYCbCrBuffered(pix1, pix2); + if (a1 < a2) + return a1 * d + 255 * (a2 - a1); + else + return a2 * d + 255 * (a1 - a2); + + //alternative? return std::sqrt(a1 * a2 * square(distYCbCrBuffered(pix1, pix2)) + square(255 * (a1 - a2))); + } +}; + + +struct ColorDistanceUnbufferedARGB +{ + static double dist(uint32_t pix1, uint32_t pix2, double luminanceWeight) + { + const double a1 = getAlpha(pix1) / 255.0 ; + const double a2 = getAlpha(pix2) / 255.0 ; + + const double d = distYCbCr(pix1, pix2, luminanceWeight); + if (a1 < a2) + return a1 * d + 255 * (a2 - a1); + else + return a2 * d + 255 * (a1 - a2); + } +}; + + +struct ColorGradientRGB +{ + template + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + pixBack = gradientRGB(pixFront, pixBack); + } +}; + +struct ColorGradientARGB +{ + template + static void alphaGrad(uint32_t& pixBack, uint32_t pixFront) + { + pixBack = gradientARGB(pixFront, pixBack); + } +}; +} + + +void xbrz::scale(size_t factor, const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, ColorFormat colFmt, const xbrz::ScalerCfg& cfg, int yFirst, int yLast) +{ + if (factor == 1) + { + std::copy(src + yFirst * srcWidth, src + yLast * srcWidth, trg); + return; + } + + static_assert(SCALE_FACTOR_MAX == 6); + switch (colFmt) + { + case ColorFormat::RGB: + switch (factor) + { + case 2: + return scaleImage, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 3: + return scaleImage, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 4: + return scaleImage, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 5: + return scaleImage, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 6: + return scaleImage, ColorDistanceRGB, OobReaderDuplicate>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + } + break; + + case ColorFormat::ARGB: + switch (factor) + { + case 2: + return scaleImage, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 3: + return scaleImage, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 4: + return scaleImage, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 5: + return scaleImage, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 6: + return scaleImage, ColorDistanceARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + } + break; + + case ColorFormat::ARGB_UNBUFFERED: + switch (factor) + { + case 2: + return scaleImage, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 3: + return scaleImage, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 4: + return scaleImage, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 5: + return scaleImage, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + case 6: + return scaleImage, ColorDistanceUnbufferedARGB, OobReaderTransparent>(src, trg, srcWidth, srcHeight, cfg, yFirst, yLast); + } + break; + } + assert(false); +} + + +bool xbrz::equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance) +{ + switch (colFmt) + { + case ColorFormat::RGB: + return ColorDistanceRGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; + case ColorFormat::ARGB: + return ColorDistanceARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; + case ColorFormat::ARGB_UNBUFFERED: + return ColorDistanceUnbufferedARGB::dist(col1, col2, luminanceWeight) < equalColorTolerance; + } + assert(false); + return false; +} + + +void xbrz::bilinearScale(const uint32_t* src, int srcWidth, int srcHeight, + /**/ uint32_t* trg, int trgWidth, int trgHeight) +{ + bilinearScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t), + trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t), + 0, trgHeight, [](uint32_t pix) { return pix; }); +} + + +void xbrz::nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, + /**/ uint32_t* trg, int trgWidth, int trgHeight) +{ + nearestNeighborScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t), + trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t), + 0, trgHeight, [](uint32_t pix) { return pix; }); +} + + +#if 0 +//#include +void bilinearScaleCpu(const uint32_t* src, int srcWidth, int srcHeight, + /**/ uint32_t* trg, int trgWidth, int trgHeight) +{ + const int TASK_GRANULARITY = 16; + + concurrency::task_group tg; + + for (int i = 0; i < trgHeight; i += TASK_GRANULARITY) + tg.run([=] + { + const int iLast = std::min(i + TASK_GRANULARITY, trgHeight); + xbrz::bilinearScale(src, srcWidth, srcHeight, srcWidth * sizeof(uint32_t), + trg, trgWidth, trgHeight, trgWidth * sizeof(uint32_t), + i, iLast, [](uint32_t pix) { return pix; }); + }); + tg.wait(); +} + + +//Perf: AMP vs CPU: merely ~10% shorter runtime (scaling 1280x800 -> 1920x1080) +//#include +void bilinearScaleAmp(const uint32_t* src, int srcWidth, int srcHeight, //throw concurrency::runtime_exception + /**/ uint32_t* trg, int trgWidth, int trgHeight) +{ + //C++ AMP reference: https://msdn.microsoft.com/en-us/library/hh289390.aspx + //introduction to C++ AMP: https://msdn.microsoft.com/en-us/magazine/hh882446.aspx + using namespace concurrency; + //TODO: pitch + + if (srcHeight <= 0 || srcWidth <= 0) return; + + const float scaleX = static_cast(trgWidth ) / srcWidth; + const float scaleY = static_cast(trgHeight) / srcHeight; + + array_view srcView(srcHeight, srcWidth, src); + array_view< uint32_t, 2> trgView(trgHeight, trgWidth, trg); + trgView.discard_data(); + + parallel_for_each(trgView.extent, [=](index<2> idx) restrict(amp) //throw ? + { + const int y = idx[0]; + const int x = idx[1]; + //Perf notes: + // -> float-based calculation is (almost) 2x as fas as double! + // -> no noticeable improvement via tiling: https://msdn.microsoft.com/en-us/magazine/hh882447.aspx + // -> no noticeable improvement with restrict(amp,cpu) + // -> iterating over y-axis only is significantly slower! + // -> pre-calculating x,y-dependent variables in a buffer + array_view<> is ~ 20 % slower! + const int y1 = srcHeight * y / trgHeight; + int y2 = y1 + 1; + if (y2 == srcHeight) --y2; + + const float yy1 = y / scaleY - y1; + const float y2y = 1 - yy1; + //------------------------------------- + const int x1 = srcWidth * x / trgWidth; + int x2 = x1 + 1; + if (x2 == srcWidth) --x2; + + const float xx1 = x / scaleX - x1; + const float x2x = 1 - xx1; + //------------------------------------- + const float x2xy2y = x2x * y2y; + const float xx1y2y = xx1 * y2y; + const float x2xyy1 = x2x * yy1; + const float xx1yy1 = xx1 * yy1; + + auto interpolate = [=](int offset) + { + /* + https://en.wikipedia.org/wiki/Bilinear_interpolation + (c11(x2 - x) + c21(x - x1)) * (y2 - y ) + + (c12(x2 - x) + c22(x - x1)) * (y - y1) + */ + const auto c11 = (srcView(y1, x1) >> (8 * offset)) & 0xff; + const auto c21 = (srcView(y1, x2) >> (8 * offset)) & 0xff; + const auto c12 = (srcView(y2, x1) >> (8 * offset)) & 0xff; + const auto c22 = (srcView(y2, x2) >> (8 * offset)) & 0xff; + + return c11 * x2xy2y + c21 * xx1y2y + + c12 * x2xyy1 + c22 * xx1yy1; + }; + + const float bi = interpolate(0); + const float gi = interpolate(1); + const float ri = interpolate(2); + const float ai = interpolate(3); + + const auto b = static_cast(bi + 0.5f); + const auto g = static_cast(gi + 0.5f); + const auto r = static_cast(ri + 0.5f); + const auto a = static_cast(ai + 0.5f); + + trgView(y, x) = (a << 24) | (r << 16) | (g << 8) | b; + }); + trgView.synchronize(); //throw ? +} +#endif diff --git a/SourceX/filters/xbrz/xbrz.h b/SourceX/filters/xbrz/xbrz.h new file mode 100644 index 000000000..d8f5d0fcb --- /dev/null +++ b/SourceX/filters/xbrz/xbrz.h @@ -0,0 +1,79 @@ +// **************************************************************************** +// * This file is part of the xBRZ project. It is distributed under * +// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * +// * * +// * Additionally and as a special exception, the author gives permission * +// * to link the code of this program with the following libraries * +// * (or with modified versions that use the same licenses), and distribute * +// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe * +// * You must obey the GNU General Public License in all respects for all of * +// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. * +// * If you modify this file, you may extend this exception to your version * +// * of the file, but you are not obligated to do so. If you do not wish to * +// * do so, delete this exception statement from your version. * +// **************************************************************************** + +#ifndef XBRZ_HEADER_3847894708239054 +#define XBRZ_HEADER_3847894708239054 + +#include //size_t +#include //uint32_t +#include +#include "xbrz_config.h" + + +namespace xbrz +{ +/* +------------------------------------------------------------------------- +| xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju | +------------------------------------------------------------------------- +using a modified approach of xBR: +http://board.byuu.org/viewtopic.php?f=10&t=2248 +- new rule set preserving small image features +- highly optimized for performance +- support alpha channel +- support multithreading +- support 64-bit architectures +- support processing image slices +- support scaling up to 6xBRZ +*/ + +enum class ColorFormat //from high bits -> low bits, 8 bit per channel +{ + RGB, //8 bit for each red, green, blue, upper 8 bits unused + ARGB, //including alpha channel, BGRA byte order on little-endian machines + ARGB_UNBUFFERED, //like ARGB, but without the one-time buffer creation overhead (ca. 100 - 300 ms) at the expense of a slightly slower scaling time +}; + +const int SCALE_FACTOR_MAX = 6; + +/* +-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only +-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image: + Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis) + CAVEAT: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition + in the target image data if you are using multiple threads for processing each enlarged slice! + +THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap! + - there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process at least 8-16 rows +*/ +void scale(size_t factor, //valid range: 2 - SCALE_FACTOR_MAX + const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight, + ColorFormat colFmt, + const ScalerCfg& cfg = ScalerCfg(), + int yFirst = 0, int yLast = std::numeric_limits::max()); //slice of source image + +void bilinearScale(const uint32_t* src, int srcWidth, int srcHeight, + /**/ uint32_t* trg, int trgWidth, int trgHeight); + +void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight, + /**/ uint32_t* trg, int trgWidth, int trgHeight); + + +//parameter tuning +bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance); +} + +#endif diff --git a/SourceX/filters/xbrz/xbrz_config.h b/SourceX/filters/xbrz/xbrz_config.h new file mode 100644 index 000000000..411649baf --- /dev/null +++ b/SourceX/filters/xbrz/xbrz_config.h @@ -0,0 +1,35 @@ +// **************************************************************************** +// * This file is part of the xBRZ project. It is distributed under * +// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * +// * * +// * Additionally and as a special exception, the author gives permission * +// * to link the code of this program with the following libraries * +// * (or with modified versions that use the same licenses), and distribute * +// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe * +// * You must obey the GNU General Public License in all respects for all of * +// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. * +// * If you modify this file, you may extend this exception to your version * +// * of the file, but you are not obligated to do so. If you do not wish to * +// * do so, delete this exception statement from your version. * +// **************************************************************************** + +#ifndef XBRZ_CONFIG_HEADER_284578425345 +#define XBRZ_CONFIG_HEADER_284578425345 + +//do NOT include any headers here! used by xBRZ_dll!!! + +namespace xbrz +{ +struct ScalerCfg +{ + double luminanceWeight = 1; + double equalColorTolerance = 0; + double centerDirectionBias = 1; + double dominantDirectionThreshold = 3600.0; + double steepDirectionThreshold = 6.0; + double newTestAttribute = 0; //unused; test new parameters +}; +} + +#endif diff --git a/SourceX/filters/xbrz/xbrz_tools.h b/SourceX/filters/xbrz/xbrz_tools.h new file mode 100644 index 000000000..c37d7ac3d --- /dev/null +++ b/SourceX/filters/xbrz/xbrz_tools.h @@ -0,0 +1,274 @@ +// **************************************************************************** +// * This file is part of the xBRZ project. It is distributed under * +// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 * +// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * +// * * +// * Additionally and as a special exception, the author gives permission * +// * to link the code of this program with the following libraries * +// * (or with modified versions that use the same licenses), and distribute * +// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe * +// * You must obey the GNU General Public License in all respects for all of * +// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. * +// * If you modify this file, you may extend this exception to your version * +// * of the file, but you are not obligated to do so. If you do not wish to * +// * do so, delete this exception statement from your version. * +// **************************************************************************** + +#ifndef XBRZ_TOOLS_H_825480175091875 +#define XBRZ_TOOLS_H_825480175091875 + +#include +#include +#include + + +namespace xbrz +{ +template inline +unsigned char getByte(uint32_t val) { return static_cast((val >> (8 * N)) & 0xff); } + +inline unsigned char getAlpha(uint32_t pix) { return getByte<3>(pix); } +inline unsigned char getRed (uint32_t pix) { return getByte<2>(pix); } +inline unsigned char getGreen(uint32_t pix) { return getByte<1>(pix); } +inline unsigned char getBlue (uint32_t pix) { return getByte<0>(pix); } + +inline uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b) { return (a << 24) | (r << 16) | (g << 8) | b; } +inline uint32_t makePixel( unsigned char r, unsigned char g, unsigned char b) { return (r << 16) | (g << 8) | b; } + +inline uint32_t rgb555to888(uint16_t pix) { return ((pix & 0x7C00) << 9) | ((pix & 0x03E0) << 6) | ((pix & 0x001F) << 3); } +inline uint32_t rgb565to888(uint16_t pix) { return ((pix & 0xF800) << 8) | ((pix & 0x07E0) << 5) | ((pix & 0x001F) << 3); } + +inline uint16_t rgb888to555(uint32_t pix) { return static_cast(((pix & 0xF80000) >> 9) | ((pix & 0x00F800) >> 6) | ((pix & 0x0000F8) >> 3)); } +inline uint16_t rgb888to565(uint32_t pix) { return static_cast(((pix & 0xF80000) >> 8) | ((pix & 0x00FC00) >> 5) | ((pix & 0x0000F8) >> 3)); } + + +template inline +Pix* byteAdvance(Pix* ptr, int bytes) +{ + using PixNonConst = typename std::remove_cv::type; + using PixByte = typename std::conditional::value, char, const char>::type; + + static_assert(std::is_integral::value, "Pix* is expected to be cast-able to char*"); + + return reinterpret_cast(reinterpret_cast(ptr) + bytes); +} + + +//fill block with the given color +template inline +void fillBlock(Pix* trg, int pitch /*[bytes]*/, Pix col, int blockWidth, int blockHeight) +{ + //for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) + // std::fill(trg, trg + blockWidth, col); + + for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch)) + for (int x = 0; x < blockWidth; ++x) + trg[x] = col; +} + + +//nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!) +template +void nearestNeighborScale(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch /*[bytes]*/, + /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch /*[bytes]*/, + int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/) +{ + static_assert(std::is_integral::value, "PixSrc* is expected to be cast-able to char*"); + static_assert(std::is_integral::value, "PixTrg* is expected to be cast-able to char*"); + + static_assert(std::is_same::value, "PixConverter returning wrong pixel format"); + + if (srcPitch < srcWidth * static_cast(sizeof(PixSrc)) || + trgPitch < trgWidth * static_cast(sizeof(PixTrg))) + { + assert(false); + return; + } + + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, trgHeight); + if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return; + + for (int y = yFirst; y < yLast; ++y) + { + const int ySrc = srcHeight * y / trgHeight; + const PixSrc* const srcLine = byteAdvance(src, ySrc * srcPitch); + PixTrg* const trgLine = byteAdvance(trg, y * trgPitch); + + for (int x = 0; x < trgWidth; ++x) + { + const int xSrc = srcWidth * x / trgWidth; + trgLine[x] = pixCvrt(srcLine[xSrc]); + } + } +} + + +//nearest-neighbor (going over source image - fast for upscaling, since source is read only once +template +void nearestNeighborScaleOverSource(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch /*[bytes]*/, + /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch /*[bytes]*/, + int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/) +{ + static_assert(std::is_integral::value, "PixSrc* is expected to be cast-able to char*"); + static_assert(std::is_integral::value, "PixTrg* is expected to be cast-able to char*"); + + static_assert(std::is_same::value, "PixConverter returning wrong pixel format"); + + if (srcPitch < srcWidth * static_cast(sizeof(PixSrc)) || + trgPitch < trgWidth * static_cast(sizeof(PixTrg))) + { + assert(false); + return; + } + + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, srcHeight); + if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) return; + + for (int y = yFirst; y < yLast; ++y) + { + //mathematically: ySrc = floor(srcHeight * yTrg / trgHeight) + // => search for integers in: [ySrc, ySrc + 1) * trgHeight / srcHeight + + //keep within for loop to support MT input slices! + const int yTrgFirst = ( y * trgHeight + srcHeight - 1) / srcHeight; //=ceil(y * trgHeight / srcHeight) + const int yTrgLast = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; //=ceil(((y + 1) * trgHeight) / srcHeight) + const int blockHeight = yTrgLast - yTrgFirst; + + if (blockHeight > 0) + { + const PixSrc* srcLine = byteAdvance(src, y * srcPitch); + /**/ PixTrg* trgLine = byteAdvance(trg, yTrgFirst * trgPitch); + int xTrgFirst = 0; + + for (int x = 0; x < srcWidth; ++x) + { + const int xTrgLast = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth; + const int blockWidth = xTrgLast - xTrgFirst; + if (blockWidth > 0) + { + xTrgFirst = xTrgLast; + + const auto trgPix = pixCvrt(srcLine[x]); + fillBlock(trgLine, trgPitch, trgPix, blockWidth, blockHeight); + trgLine += blockWidth; + } + } + } + } +} + + +template +void bilinearScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch, + /**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch, + int yFirst, int yLast, PixConverter pixCvrt /*convert uint32_t to PixTrg*/) +{ + static_assert(std::is_integral::value, "PixTrg* is expected to be cast-able to char*"); + static_assert(std::is_same::value, "PixConverter returning wrong pixel format"); + + if (srcPitch < srcWidth * static_cast(sizeof(uint32_t)) || + trgPitch < trgWidth * static_cast(sizeof(PixTrg))) + { + assert(false); + return; + } + + yFirst = std::max(yFirst, 0); + yLast = std::min(yLast, trgHeight); + if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return; + + const double scaleX = static_cast(trgWidth ) / srcWidth; + const double scaleY = static_cast(trgHeight) / srcHeight; + + //perf notes: + // -> double-based calculation is (slightly) faster than float + // -> pre-calculation gives significant boost; std::vector<> memory allocation is negligible! + struct CoeffsX + { + int x1 = 0; + int x2 = 0; + double xx1 = 0; + double x2x = 0; + }; + + std::vector buf(trgWidth); + for (int x = 0; x < trgWidth; ++x) + { + const int x1 = srcWidth * x / trgWidth; + int x2 = x1 + 1; + if (x2 == srcWidth) --x2; + + const double xx1 = x / scaleX - x1; + const double x2x = 1 - xx1; + + struct CoeffsX buf_struct; + + buf_struct.x1=x1; + buf_struct.x2=x2; + buf_struct.xx1=xx1; + buf_struct.x2x=x2x; + + buf[x] = buf_struct; + } + + for (int y = yFirst; y < yLast; ++y) + { + const int y1 = srcHeight * y / trgHeight; + int y2 = y1 + 1; + if (y2 == srcHeight) --y2; + + const double yy1 = y / scaleY - y1; + const double y2y = 1 - yy1; + + const uint32_t* const srcLine = byteAdvance(src, y1 * srcPitch); + const uint32_t* const srcLineNext = byteAdvance(src, y2 * srcPitch); + PixTrg* const trgLine = byteAdvance(trg, y * trgPitch); + + for (int x = 0; x < trgWidth; ++x) + { + //perf: do NOT "simplify" the variable layout without measurement! + const int x1 = buf[x].x1; + const int x2 = buf[x].x2; + const double xx1 = buf[x].xx1; + const double x2x = buf[x].x2x; + + const double x2xy2y = x2x * y2y; + const double xx1y2y = xx1 * y2y; + const double x2xyy1 = x2x * yy1; + const double xx1yy1 = xx1 * yy1; + + auto interpolate = [=](int offset) + { + /* https://en.wikipedia.org/wiki/Bilinear_interpolation + (c11(x2 - x) + c21(x - x1)) * (y2 - y ) + + (c12(x2 - x) + c22(x - x1)) * (y - y1) */ + const auto c11 = (srcLine [x1] >> (8 * offset)) & 0xff; + const auto c21 = (srcLine [x2] >> (8 * offset)) & 0xff; + const auto c12 = (srcLineNext[x1] >> (8 * offset)) & 0xff; + const auto c22 = (srcLineNext[x2] >> (8 * offset)) & 0xff; + + return c11 * x2xy2y + c21 * xx1y2y + + c12 * x2xyy1 + c22 * xx1yy1; + }; + + const double bi = interpolate(0); + const double gi = interpolate(1); + const double ri = interpolate(2); + const double ai = interpolate(3); + + const auto b = static_cast(bi + 0.5); + const auto g = static_cast(gi + 0.5); + const auto r = static_cast(ri + 0.5); + const auto a = static_cast(ai + 0.5); + + const uint32_t trgPix = (a << 24) | (r << 16) | (g << 8) | b; + + trgLine[x] = pixCvrt(trgPix); + } + } +} +} + +#endif //XBRZ_TOOLS_H_825480175091875 diff --git a/SourceX/miniwin/misc_msg.cpp b/SourceX/miniwin/misc_msg.cpp index 710cf86df..4dc84286b 100644 --- a/SourceX/miniwin/misc_msg.cpp +++ b/SourceX/miniwin/misc_msg.cpp @@ -17,6 +17,14 @@ #include #endif +/* mouse clipping */ +short diff_x, diff_y; +static short mx, my; +static short old_x, old_y; +int warp_direction_x; +int warp_direction_y; +/* mouse clipping */ + /** @file * * * Windows message handling and keyboard event conversion for SDL. @@ -32,6 +40,18 @@ int mouseWarpingY; void SetCursorPos(int X, int Y) { + /* mouse clipping - adjust mouse warping */ + warp_direction_x = 1; + warp_direction_y = 1; + if( MouseX > X ) warp_direction_x = 1; + if( MouseX < X ) warp_direction_x = -1; + if( MouseY > Y ) warp_direction_y = 1; + if( MouseY < Y ) warp_direction_y = -1; + if(warp_direction_x == -1) X = old_x + (cursW >> 1); + if(warp_direction_x == 1) X = old_x - (cursW >> 1); + if(warp_direction_y == -1) Y = old_y + (cursH >> 1); + if(warp_direction_y == 1) Y = old_y - (cursH >> 1); + /* mouse clipping - adjust mouse warping */ mouseWarpingX = X; mouseWarpingY = Y; mouseWarping = true; @@ -246,6 +266,24 @@ namespace { LPARAM position_for_mouse(short x, short y) { + /* mouse clipping */ + diff_x = x - old_x; + diff_y = y - old_y; + + old_x = x; + old_y = y; + + mx += diff_x; + my += diff_y; + + if(mx < 0) mx = 0; + if(mx > 640-1) mx = 640-1; + if(my < 0) my = 0; + if(my > 480-1) my = 480-1; + + x=mx; + y=my; + /* mouse clipping */ return (((uint16_t)(y & 0xFFFF)) << 16) | (uint16_t)(x & 0xFFFF); } diff --git a/SourceX/storm/storm.cpp b/SourceX/storm/storm.cpp index fa6339b24..16092fc5c 100644 --- a/SourceX/storm/storm.cpp +++ b/SourceX/storm/storm.cpp @@ -589,11 +589,11 @@ void SVidPlayBegin(char *filename, int a2, int a3, int a4, int a5, int flags, HA #ifndef USE_SDL1 if (renderer) { SDL_DestroyTexture(texture); - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, SVidWidth, SVidHeight); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, SVidWidth*2, SVidHeight*2); /* hardcoding for cutscenes */ if (texture == NULL) { ErrSdl(); } - if (SDL_RenderSetLogicalSize(renderer, SVidWidth, SVidHeight) <= -1) { + if (SDL_RenderSetLogicalSize(renderer, 1920/*SVidWidth*/, ((1080*SVidHeight)/180)/*SVidHeight*/) <= -1) { /* hardcoding for cutscenes */ ErrSdl(); } } @@ -792,11 +792,11 @@ void SVidPlayEnd(HANDLE video) #ifndef USE_SDL1 if (renderer) { SDL_DestroyTexture(texture); - texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, SCREEN_WIDTH, SCREEN_HEIGHT); + texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB888, SDL_TEXTUREACCESS_STREAMING, 1280/*SCREEN_WIDTH*/, 960/*SCREEN_HEIGHT*/); if (texture == NULL) { ErrSdl(); } - if (renderer && SDL_RenderSetLogicalSize(renderer, SCREEN_WIDTH, SCREEN_HEIGHT) <= -1) { + if (renderer && SDL_RenderSetLogicalSize(renderer, 1280/*SCREEN_WIDTH*/, 960/*SCREEN_HEIGHT*/) <= -1) { ErrSdl(); } } diff --git a/defs.h b/defs.h index 161810253..ba43b9082 100644 --- a/defs.h +++ b/defs.h @@ -56,6 +56,8 @@ #define VOLUME_MIN -1600 #define VOLUME_MAX 0 +#define NUM_TOWNERS 16 + // todo: enums #define NUMLEVELS 17 #define SMITH_ITEMS 20 diff --git a/enums.h b/enums.h index 7ee99c270..c400de1fc 100644 --- a/enums.h +++ b/enums.h @@ -4,6 +4,8 @@ * Various global enumerators. */ +DEVILUTION_BEGIN_NAMESPACE + typedef enum item_quality { ITEM_QUALITY_NORMAL = 0, ITEM_QUALITY_MAGIC = 1, @@ -2940,3 +2942,5 @@ typedef enum conn_type { #endif SELCONN_LOOPBACK, } conn_type; + +DEVILUTION_END_NAMESPACE diff --git a/structs.h b/structs.h index fe87ff40e..566172af5 100644 --- a/structs.h +++ b/structs.h @@ -4,6 +4,8 @@ * Various global structures. */ +DEVILUTION_BEGIN_NAMESPACE + ////////////////////////////////////////////////// // control ////////////////////////////////////////////////// @@ -1585,3 +1587,5 @@ typedef struct TDataInfo { DWORD destOffset; DWORD size; } TDataInfo; + +DEVILUTION_END_NAMESPACE diff --git a/types.h b/types.h index d3e377cc1..a351faf37 100644 --- a/types.h +++ b/types.h @@ -14,8 +14,6 @@ #include "thread.h" #include "ui_fwd.h" -DEVILUTION_BEGIN_NAMESPACE - #include #include "defs.h" #include "enums.h"