├── src ├── framework │ ├── misc │ │ ├── Flags.cpp │ │ ├── fcaseopen.h │ │ ├── CMakeLists.txt │ │ ├── Ratio.cpp │ │ ├── PropertiesParser.h │ │ ├── MTRand.h │ │ ├── Ratio.h │ │ ├── Flags.h │ │ ├── Point.h │ │ ├── Debug.h │ │ ├── Buffer.h │ │ ├── ModVal.h │ │ ├── XMLParser.h │ │ ├── RegistryEmulator.h │ │ ├── SexyMatrix.h │ │ ├── memmgr.h │ │ ├── DescParser.h │ │ ├── Rect.h │ │ └── KeyCodes.h │ ├── imagelib │ │ ├── CMakeLists.txt │ │ └── ImageLib.h │ ├── paklib │ │ └── CMakeLists.txt │ ├── widget │ │ ├── SliderListener.h │ │ ├── Insets.cpp │ │ ├── ScrollListener.h │ │ ├── CheckboxListener.h │ │ ├── DialogListener.h │ │ ├── Insets.h │ │ ├── ListListener.h │ │ ├── CMakeLists.txt │ │ ├── DialogButton.h │ │ ├── ButtonListener.h │ │ ├── EditListener.h │ │ ├── HyperlinkWidget.h │ │ ├── ScrollbuttonWidget.h │ │ ├── Slider.h │ │ ├── Checkbox.h │ │ ├── HyperlinkWidget.cpp │ │ ├── TextWidget.h │ │ ├── ScrollbuttonWidget.cpp │ │ ├── ButtonWidget.h │ │ ├── Checkbox.cpp │ │ ├── ScrollbarWidget.h │ │ ├── DialogButton.cpp │ │ ├── WidgetContainer.h │ │ ├── ListWidget.h │ │ └── EditWidget.h │ ├── graphics │ │ ├── CMakeLists.txt │ │ ├── TriVertex.h │ │ ├── shaders │ │ │ ├── shader.vert │ │ │ ├── CMakeLists.txt │ │ │ └── water.comp │ │ ├── Font.h │ │ ├── Font.cpp │ │ ├── Color.h │ │ ├── VkInterface.h │ │ ├── WindowInterface.h │ │ ├── Color.cpp │ │ └── VkCommon.h │ ├── resource.h │ ├── CursorWidget.h │ ├── sound │ │ ├── DummySoundInstance.h │ │ ├── SoundInstance.h │ │ ├── DummySoundManager.h │ │ ├── DummyMusicInterface.h │ │ ├── SoundManager.h │ │ ├── BassSoundInstance.h │ │ ├── MusicInterface.h │ │ ├── CMakeLists.txt │ │ ├── BassSoundManager.h │ │ ├── BassMusicInterface.h │ │ └── BassSoundInstance.cpp │ ├── LawnProject.rc │ ├── SexyApp.h │ └── .gitattributes ├── lawn │ ├── Cutscene.h │ ├── LawnMower.cpp │ ├── Projectile.cpp │ ├── widget │ │ ├── GameButton.cpp │ │ ├── UserDialog.cpp │ │ ├── AlmanacDialog.cpp │ │ ├── ImitaterDialog.cpp │ │ ├── CMakeLists.txt │ │ ├── ImitaterDialog.h │ │ ├── ContinueDialog.h │ │ ├── CheatDialog.h │ │ ├── NewUserDialog.h │ │ ├── UserDialog.h │ │ ├── AchievementsScreen.h │ │ ├── NewOptionsDialog.h │ │ ├── TitleScreen.h │ │ ├── AwardScreen.h │ │ ├── LawnDialog.h │ │ ├── AlmanacDialog.h │ │ ├── NewUserDialog.cpp │ │ └── ChallengeScreen.h │ ├── system │ │ ├── CMakeLists.txt │ │ ├── TypingCheck.h │ │ ├── TypingCheck.cpp │ │ ├── PoolEffect.h │ │ ├── ProfileMgr.h │ │ ├── ReanimationLawn.h │ │ └── SaveGame.h │ ├── BoardInclude.h │ ├── CMakeLists.txt │ ├── GameObject.h │ ├── GameObject.cpp │ ├── CursorObject.h │ ├── ToolTipWidget.h │ ├── LawnMower.h │ ├── MessageWidget.h │ ├── LawnCommon.h │ ├── Coin.h │ ├── SeedPacket.h │ ├── Projectile.h │ └── GridItem.h ├── res │ ├── Cursor13.cur │ └── CMakeLists.txt ├── compiler │ ├── CMakeLists.txt │ ├── array.h │ ├── hash.h │ ├── quick_sort.h │ └── map.h ├── todlib │ ├── CMakeLists.txt │ ├── FilterEffect.h │ ├── ReanimAtlas.h │ ├── EffectSystem.h │ ├── TodDebug.cpp │ ├── Trail.h │ └── TodList.cpp ├── CMakeLists.txt ├── main.cpp └── GameConstants.h ├── .gitattributes ├── tools ├── trackdef-token-matcher.re ├── SelectorScreen.reanim.diff └── unpak.c ├── configure.sh ├── profile.sh ├── clang-format-all.sh ├── install.sh ├── run.sh ├── toolchain.cmake ├── .clang-format ├── CMakeSettings.json ├── cmake └── embed_binary.cmake └── re-plants-vs-zombies.sublime-project /src/framework/misc/Flags.cpp: -------------------------------------------------------------------------------- 1 | #include "Flags.h" 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /src/lawn/Cutscene.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/Cutscene.h -------------------------------------------------------------------------------- /src/res/Cursor13.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/res/Cursor13.cur -------------------------------------------------------------------------------- /src/lawn/LawnMower.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/LawnMower.cpp -------------------------------------------------------------------------------- /src/lawn/Projectile.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/Projectile.cpp -------------------------------------------------------------------------------- /tools/trackdef-token-matcher.re: -------------------------------------------------------------------------------- 1 | (?:[-0-9.]+|\[(?:(?:[-0-9.]+(?: [a-Z]+)? [-0-9.]+)|(?:[-0-9.]+))\])(,[-0-9.]+)? -------------------------------------------------------------------------------- /src/lawn/widget/GameButton.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/widget/GameButton.cpp -------------------------------------------------------------------------------- /src/lawn/widget/UserDialog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/widget/UserDialog.cpp -------------------------------------------------------------------------------- /src/lawn/widget/AlmanacDialog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/widget/AlmanacDialog.cpp -------------------------------------------------------------------------------- /src/framework/imagelib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | "ImageLib.cpp" 3 | "ImageLib.h" 4 | ) 5 | -------------------------------------------------------------------------------- /src/lawn/widget/ImitaterDialog.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minerscale/re-plants-vs-zombies/HEAD/src/lawn/widget/ImitaterDialog.cpp -------------------------------------------------------------------------------- /src/framework/paklib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | "PakInterface.cpp" 3 | "PakInterface.h" 4 | ) 5 | -------------------------------------------------------------------------------- /configure.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm -rf build 4 | rm -f compile_commands.json 5 | cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -G Ninja -B build 6 | -------------------------------------------------------------------------------- /profile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd tools/run/ 4 | 5 | perf record -e cycles -e cache-misses -e branch-misses -g --call-graph=dwarf -F 762 ./PlantsVsZombies 6 | #perf script -F +pid > test-conv.perf 7 | -------------------------------------------------------------------------------- /clang-format-all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | git ls-tree -r $(git rev-parse --abbrev-ref HEAD) --name-only | 4 | grep -E "(\.cpp|\.c|\.hpp|\.h)$" | 5 | while read line; do 6 | clang-format -style=file -i "$line"; 7 | done 8 | -------------------------------------------------------------------------------- /tools/SelectorScreen.reanim.diff: -------------------------------------------------------------------------------- 1 | 24110c24110 2 | < 405.0624.0IMAGE_REANIM_SELECTORSCREEN_STARTADVENTURE_BUTTON1 3 | --- 4 | > 405.0624.0IMAGE_REANIM_SELECTORSCREEN_ADVENTURE_BUTTON 5 | -------------------------------------------------------------------------------- /src/compiler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | ${CMAKE_CURRENT_SOURCE_DIR}/quick_sort.h 3 | ${CMAKE_CURRENT_SOURCE_DIR}/hash.h 4 | ${CMAKE_CURRENT_SOURCE_DIR}/map.h 5 | ${CMAKE_CURRENT_SOURCE_DIR}/array.h 6 | ) -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cmake --build build -j6 4 | if [ $? -eq 0 ]; then 5 | mkdir -p tools/run 6 | cp build/compile_commands.json . 7 | cp build/PlantsVsZombies tools/run/PlantsVsZombies 8 | cp build/libbass.so tools/run/libbass.so 9 | fi 10 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | rm -f tools/run/PlantsVsZombies 4 | 5 | ./install.sh 6 | cd tools/run 7 | 8 | if test -f ./PlantsVsZombies 9 | then 10 | if [[ $1 = "-g" ]] 11 | then 12 | lldb ./PlantsVsZombies 13 | else 14 | gamemoderun ./PlantsVsZombies 15 | fi 16 | fi 17 | -------------------------------------------------------------------------------- /src/lawn/system/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | Music.cpp 3 | PlayerInfo.cpp 4 | SaveGame.cpp 5 | ReanimationLawn.cpp 6 | ProfileMgr.cpp 7 | PoolEffect.cpp 8 | TypingCheck.cpp 9 | DataSync.cpp 10 | ) 11 | -------------------------------------------------------------------------------- /toolchain.cmake: -------------------------------------------------------------------------------- 1 | #set(CMAKE_SYSTEM_NAME Windows) 2 | set(CMAKE_SYSTEM_PROCESSOR x86_64) 3 | set(CMAKE_BUILD_TYPE Release) 4 | set(CHOST "") 5 | set(CMAKE_C_COMPILER "clang") 6 | set(CMAKE_CXX_COMPILER "clang++") 7 | #set(CMAKE_RC_COMPILER "${CHOST}-windres") 8 | set(CMAKE_FIND_ROOT_PATH "/usr/${CHOST}") 9 | -------------------------------------------------------------------------------- /src/framework/widget/SliderListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __SLIDERLISTENER_H__ 2 | #define __SLIDERLISTENER_H__ 3 | 4 | namespace Sexy { 5 | class SliderListener { 6 | public: 7 | virtual void SliderVal(int theId, double theVal) = 0; 8 | }; 9 | } // namespace Sexy 10 | 11 | #endif //__SLIDERLISTENER_H__ 12 | -------------------------------------------------------------------------------- /src/framework/widget/Insets.cpp: -------------------------------------------------------------------------------- 1 | #include "Insets.h" 2 | 3 | using namespace Sexy; 4 | 5 | Insets::Insets() : mLeft(0), mTop(0), mRight(0), mBottom(0) {} 6 | 7 | Insets::Insets(int theLeft, int theTop, int theRight, int theBottom) 8 | : mLeft(theLeft), mTop(theTop), mRight(theRight), mBottom(theBottom) {} 9 | -------------------------------------------------------------------------------- /src/framework/widget/ScrollListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCROLLLISTENER_H__ 2 | #define __SCROLLLISTENER_H__ 3 | 4 | namespace Sexy { 5 | class ScrollListener { 6 | public: 7 | virtual void ScrollPosition(int theId, double thePosition) = 0; 8 | }; 9 | } // namespace Sexy 10 | 11 | #endif // __SCROLLLISTENER_H__ 12 | -------------------------------------------------------------------------------- /src/framework/widget/CheckboxListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHECKBOX_LISTENER__ 2 | #define __CHECKBOX_LISTENER__ 3 | 4 | namespace Sexy { 5 | class CheckboxListener { 6 | public: 7 | virtual void CheckboxChecked(int theId, bool checked) = 0; 8 | }; 9 | } // namespace Sexy 10 | 11 | #endif //__CHECKBOX_LISTENER__ 12 | -------------------------------------------------------------------------------- /src/framework/misc/fcaseopen.h: -------------------------------------------------------------------------------- 1 | #ifndef fcaseopen_h 2 | #define fcaseopen_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | FILE *fcaseopen(const char *path, const char *mode); 9 | 10 | #if !defined(_WIN32) 11 | std::string casepath(const std::string &path); 12 | #else 13 | #define casepath(path) (path) 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/framework/widget/DialogListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __DIALOGLISTENER_H__ 2 | #define __DIALOGLISTENER_H__ 3 | 4 | namespace Sexy { 5 | class DialogListener { 6 | public: 7 | virtual void DialogButtonPress(int theDialogId, int theButtonId) = 0; 8 | virtual void DialogButtonDepress(int theDialogId, int theButtonId) = 0; 9 | }; 10 | } // namespace Sexy 11 | 12 | #endif // __DIALOGLISTENER_H__ 13 | -------------------------------------------------------------------------------- /src/todlib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | Attachment.cpp 3 | EffectSystem.cpp 4 | ReanimAtlas.cpp 5 | TodCommon.cpp 6 | TodFoley.cpp 7 | TodParticle.cpp 8 | Trail.cpp 9 | Definition.cpp 10 | FilterEffect.cpp 11 | Reanimator.cpp 12 | TodDebug.cpp 13 | TodList.cpp 14 | TodStringFile.cpp 15 | ) 16 | -------------------------------------------------------------------------------- /src/framework/widget/Insets.h: -------------------------------------------------------------------------------- 1 | #ifndef __INSETS_H__ 2 | #define __INSETS_H__ 3 | 4 | namespace Sexy { 5 | class Insets { 6 | public: 7 | int mLeft; 8 | int mTop; 9 | int mRight; 10 | int mBottom; 11 | 12 | public: 13 | Insets(); 14 | Insets(int theLeft, int theTop, int theRight, int theBottom); 15 | // Insets(const Insets& theInsets); 16 | }; 17 | } // namespace Sexy 18 | 19 | #endif //__INSETS_H__ 20 | -------------------------------------------------------------------------------- /src/framework/widget/ListListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __LISTLISTENER_H__ 2 | #define __LISTLISTENER_H__ 3 | 4 | namespace Sexy { 5 | class ListListener { 6 | public: 7 | virtual void ListClicked(int theId, int theIdx, int theClickCount) = 0; 8 | virtual void ListClosed(int theId) = 0; 9 | virtual void ListHiliteChanged(int theId, int theOldIdx, int theNewIdx) = 0; 10 | }; 11 | } // namespace Sexy 12 | 13 | #endif //__LISTLISTENER_H__ 14 | -------------------------------------------------------------------------------- /src/framework/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | "Buffer.cpp" 3 | "Debug.cpp" 4 | "DescParser.cpp" 5 | "Flags.cpp" 6 | "KeyCodes.cpp" 7 | "MTRand.cpp" 8 | "PropertiesParser.cpp" 9 | "Ratio.cpp" 10 | "ResourceManager.cpp" 11 | "SexyMatrix.cpp" 12 | "XMLParser.cpp" 13 | "RegistryEmulator.cpp" 14 | "fcaseopen.cpp" 15 | ) 16 | -------------------------------------------------------------------------------- /src/framework/graphics/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(ExternalProject) 2 | 3 | find_package(Vulkan REQUIRED) 4 | 5 | target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan) 6 | 7 | target_sources(${PROJECT_NAME} PRIVATE 8 | Color.cpp 9 | Color.h 10 | Font.cpp 11 | Graphics.cpp 12 | Image.cpp 13 | ImageFont.cpp 14 | VkInterface.cpp 15 | VkImage.cpp 16 | ) 17 | 18 | add_subdirectory(shaders) 19 | -------------------------------------------------------------------------------- /src/framework/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ 生成的包含文件。 3 | // 供 LawnProject.rc 使用 4 | // 5 | #define IDC_CURSOR1 102 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 103 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /src/framework/CursorWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURSORWIDGET_H__ 2 | #define __CURSORWIDGET_H__ 3 | 4 | #include "Point.h" 5 | #include "Widget.h" 6 | 7 | namespace Sexy { 8 | 9 | class Image; 10 | 11 | class CursorWidget : public Widget { 12 | public: 13 | Image *mImage; 14 | 15 | public: 16 | CursorWidget(); 17 | 18 | virtual void Draw(Graphics *g); 19 | void SetImage(Image *theImage); 20 | Point GetHotspot(); 21 | }; 22 | 23 | } // namespace Sexy 24 | 25 | #endif //__CURSORWIDGET_H__ 26 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | ColumnLimit: 120 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: BlockIndent 6 | AlignArrayOfStructures: Left 7 | AlignConsecutiveShortCaseStatements: 8 | Enabled: true 9 | AllowShortBlocksOnASingleLine: Empty 10 | AllowShortCaseLabelsOnASingleLine: true 11 | AllowShortIfStatementsOnASingleLine: AllIfsAndElse 12 | IndentWidth: 4 13 | LineEnding: LF 14 | NamespaceIndentation: Inner 15 | TabWidth: 4 16 | BraceWrapping: 17 | AfterControlStatement: MultiLine 18 | -------------------------------------------------------------------------------- /src/framework/widget/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | "ButtonWidget.cpp" 3 | "Checkbox.cpp" 4 | "Dialog.cpp" 5 | "DialogButton.cpp" 6 | "EditWidget.cpp" 7 | "HyperlinkWidget.cpp" 8 | "Insets.cpp" 9 | "ListWidget.cpp" 10 | "ScrollbarWidget.cpp" 11 | "ScrollbuttonWidget.cpp" 12 | "Slider.cpp" 13 | "TextWidget.cpp" 14 | "Widget.cpp" 15 | "WidgetContainer.cpp" 16 | "WidgetManager.cpp" 17 | ) 18 | -------------------------------------------------------------------------------- /src/framework/widget/DialogButton.h: -------------------------------------------------------------------------------- 1 | #ifndef __DIALOGBUTTON_H__ 2 | #define __DIALOGBUTTON_H__ 3 | 4 | #include "ButtonWidget.h" 5 | 6 | namespace Sexy { 7 | class DialogButton : public ButtonWidget { 8 | public: 9 | Image *mComponentImage; 10 | int mTranslateX, mTranslateY; 11 | int mTextOffsetX, mTextOffsetY; 12 | 13 | public: 14 | DialogButton(Image *theComponentImage, int theId, ButtonListener *theListener); 15 | 16 | void Draw(Graphics *g) override; 17 | }; 18 | } // namespace Sexy 19 | 20 | #endif //__DIALOGBUTTON_H__ 21 | -------------------------------------------------------------------------------- /src/lawn/BoardInclude.h: -------------------------------------------------------------------------------- 1 | #include "Board.h" 2 | #include "Challenge.h" 3 | #include "Coin.h" 4 | #include "CursorObject.h" 5 | #include "Cutscene.h" 6 | #include "GameConstants.h" 7 | #include "GridItem.h" 8 | #include "LawnApp.h" 9 | #include "LawnMower.h" 10 | #include "MessageWidget.h" 11 | #include "Plant.h" 12 | #include "Projectile.h" 13 | #include "Resources.h" 14 | #include "SeedPacket.h" 15 | #include "ToolTipWidget.h" 16 | #include "Zombie.h" 17 | #include "graphics/Graphics.h" 18 | #include "misc/Debug.h" 19 | #include "widget/GameButton.h" 20 | -------------------------------------------------------------------------------- /src/lawn/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | Board.cpp 3 | LawnMower.cpp 4 | GameObject.cpp 5 | SeedPacket.cpp 6 | CutScene.cpp 7 | Challenge.cpp 8 | CursorObject.cpp 9 | Coin.cpp 10 | Projectile.cpp 11 | Plant.cpp 12 | Zombie.cpp 13 | ToolTipWidget.cpp 14 | ZenGarden.cpp 15 | MessageWidget.cpp 16 | LawnCommon.cpp 17 | GridItem.cpp 18 | ) 19 | 20 | add_subdirectory(system) 21 | add_subdirectory(widget) 22 | -------------------------------------------------------------------------------- /src/framework/widget/ButtonListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUTTONLISTENER_H__ 2 | #define __BUTTONLISTENER_H__ 3 | 4 | namespace Sexy { 5 | class ButtonListener { 6 | public: 7 | virtual void ButtonPress(int theId) = 0; 8 | virtual void ButtonDepress(int theId) = 0; 9 | virtual void ButtonDownTick(int theId) = 0; 10 | virtual void ButtonMouseEnter(int theId) = 0; 11 | virtual void ButtonMouseLeave(int theId) = 0; 12 | virtual void ButtonMouseMove(int theId, int theX, int theY) = 0; 13 | }; 14 | } // namespace Sexy 15 | 16 | #endif //__BUTTONLISTENER_H__ 17 | -------------------------------------------------------------------------------- /src/lawn/widget/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_sources(${PROJECT_NAME} PRIVATE 2 | NewUserDialog.cpp 3 | AlmanacDialog.cpp 4 | SeedChooserScreen.cpp 5 | ImitaterDialog.cpp 6 | ContinueDialog.cpp 7 | AwardScreen.cpp 8 | GameButton.cpp 9 | LawnDialog.cpp 10 | GameSelector.cpp 11 | StoreScreen.cpp 12 | CreditScreen.cpp 13 | AchievementsScreen.cpp 14 | UserDialog.cpp 15 | ChallengeScreen.cpp 16 | NewOptionsDialog.cpp 17 | CheatDialog.cpp 18 | TitleScreen.cpp 19 | ) 20 | -------------------------------------------------------------------------------- /src/framework/widget/EditListener.h: -------------------------------------------------------------------------------- 1 | #ifndef __EDITLISTENER_H__ 2 | #define __EDITLISTENER_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | class EditListener { 8 | public: 9 | virtual void EditWidgetText(int theId, const SexyString &theString) = 0; 10 | 11 | // virtual bool AllowKey(int theId, KeyCode theKey) { return true; } 12 | // virtual bool AllowChar(int theId, SexyChar theChar) { return true; } 13 | // virtual bool AllowText(int theId, const SexyString& theText) { return true; } 14 | }; 15 | } // namespace Sexy 16 | 17 | #endif //__EDITLISTENER_H__ 18 | -------------------------------------------------------------------------------- /src/lawn/GameObject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "framework/graphics/Graphics.h" 4 | 5 | using namespace Sexy; 6 | 7 | class LawnApp; 8 | class Board; 9 | 10 | class GameObject { 11 | public: 12 | LawnApp *mApp; 13 | Board *mBoard; 14 | int mX; 15 | int mY; 16 | int mWidth; 17 | int mHeight; 18 | bool mVisible; 19 | int mRow; 20 | int mRenderOrder; 21 | 22 | public: 23 | /*inline*/ GameObject(); 24 | /*inline*/ bool BeginDraw(Graphics *g) const; 25 | /*inline*/ void EndDraw(Graphics *g); 26 | /*inline*/ void MakeParentGraphicsFrame(Graphics *g); 27 | }; 28 | -------------------------------------------------------------------------------- /src/framework/widget/HyperlinkWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __HYPERLINKWIDGET_H__ 2 | #define __HYPERLINKWIDGET_H__ 3 | 4 | #include "ButtonWidget.h" 5 | 6 | namespace Sexy { 7 | class HyperlinkWidget : public ButtonWidget { 8 | public: 9 | Color mColor; 10 | Color mOverColor; 11 | int mUnderlineSize; 12 | int mUnderlineOffset; 13 | 14 | public: 15 | HyperlinkWidget(int theId, ButtonListener *theButtonListener); 16 | 17 | void Draw(Graphics *g) override; 18 | void MouseEnter() override; 19 | void MouseLeave() override; 20 | }; 21 | } // namespace Sexy 22 | 23 | #endif //__HYPERLINKWIDGET_H__ 24 | -------------------------------------------------------------------------------- /src/compiler/array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace compiler { 4 | template static constexpr auto SparseArray() { 5 | using T = decltype(arr)::value_type::second_type; 6 | 7 | constexpr auto max_key = std::max_element(arr.begin(), arr.end(), [](const auto &left, const auto &right) { 8 | return left.first < right.first; 9 | })->first; 10 | 11 | std::array sparse_array{}; 12 | 13 | for (auto it : arr) { 14 | sparse_array[it.first] = it.second; 15 | } 16 | 17 | return sparse_array; 18 | } 19 | } // namespace compiler -------------------------------------------------------------------------------- /src/lawn/system/TypingCheck.h: -------------------------------------------------------------------------------- 1 | #ifndef __TYPINGCHECK_H__ 2 | #define __TYPINGCHECK_H__ 3 | 4 | #include "framework/misc/KeyCodes.h" 5 | #include 6 | 7 | class TypingCheck { 8 | protected: 9 | std::string mPhrase; 10 | std::string mRecentTyping; 11 | 12 | public: 13 | TypingCheck() : mPhrase() {} 14 | 15 | TypingCheck(const std::string &thePhrase); 16 | 17 | void SetPhrase(const std::string &thePhrase); 18 | /*inline*/ void AddKeyCode(Sexy::KeyCode theKeyCode); 19 | void AddChar(char theChar); 20 | /*inline*/ bool Check(); 21 | bool Check(Sexy::KeyCode theKeyCode); 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lawn/GameObject.cpp: -------------------------------------------------------------------------------- 1 | #include "GameObject.h" 2 | #include "LawnApp.h" 3 | 4 | GameObject::GameObject() { 5 | mApp = gLawnApp; 6 | mBoard = gLawnApp->mBoard; 7 | mX = 0; 8 | mY = 0; 9 | mWidth = 0; 10 | mHeight = 0; 11 | mVisible = true; 12 | mRow = -1; 13 | mRenderOrder = RenderLayer::RENDER_LAYER_TOP; 14 | } 15 | 16 | bool GameObject::BeginDraw(Graphics *g) const { 17 | if (!mVisible) return false; 18 | 19 | g->Translate(mX, mY); 20 | return true; 21 | } 22 | 23 | void GameObject::EndDraw(Graphics *g) { g->Translate(-mX, -mY); } 24 | 25 | void GameObject::MakeParentGraphicsFrame(Graphics *g) { g->Translate(-mX, -mY); } 26 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | target_compile_definitions(${PROJECT_NAME} PRIVATE 2 | "$<$:" 3 | "_DEBUG;" 4 | ">" 5 | "$<$:" 6 | "NDEBUG;" 7 | "RELEASEFINAL;" 8 | ">" 9 | ) 10 | 11 | target_include_directories(${PROJECT_NAME} PRIVATE 12 | "${CMAKE_BINARY_DIR}/include" 13 | "${CMAKE_SOURCE_DIR}/src" 14 | ) 15 | 16 | target_sources(${PROJECT_NAME} PRIVATE 17 | main.cpp 18 | LawnApp.cpp 19 | Resources.cpp 20 | ) 21 | 22 | add_subdirectory(framework) 23 | add_subdirectory(todlib) 24 | add_subdirectory(lawn) 25 | add_subdirectory(res) 26 | add_subdirectory(compiler) 27 | -------------------------------------------------------------------------------- /src/framework/widget/ScrollbuttonWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCROLLBUTTONWIDGET_H__ 2 | #define __SCROLLBUTTONWIDGET_H__ 3 | 4 | #include "widget/ButtonWidget.h" 5 | 6 | namespace Sexy { 7 | class ButtonListener; 8 | 9 | class ScrollbuttonWidget : public ButtonWidget { 10 | public: 11 | bool mHorizontal; 12 | 13 | // mType is a new way of doing things (1 = up, 2 = down, 3 = left, 4 = right). 14 | // This overrides mHorizontal and mId. 15 | int mType; 16 | 17 | public: 18 | ScrollbuttonWidget(int theId, ButtonListener *theButtonListener, int theType = 0); 19 | ~ScrollbuttonWidget() override; 20 | 21 | void Draw(Graphics *g) override; 22 | }; 23 | } // namespace Sexy 24 | 25 | #endif //__SCROLLBUTTONWIDGET_H__ 26 | -------------------------------------------------------------------------------- /src/framework/misc/Ratio.cpp: -------------------------------------------------------------------------------- 1 | #include "Ratio.h" 2 | 3 | namespace Sexy { 4 | Ratio::Ratio() : mNumerator(1), mDenominator(1) {} 5 | 6 | Ratio::Ratio(int theNumerator, int theDenominator) { Set(theNumerator, theDenominator); } 7 | 8 | void Ratio::Set(int theNumerator, int theDenominator) { 9 | // find the greatest-common-denominator of theNumerator and theDenominator. 10 | int a = theNumerator; 11 | int b = theDenominator; 12 | while (b != 0) { 13 | int t = b; 14 | b = a % b; 15 | a = t; 16 | } 17 | 18 | // divide by the g-c-d to reduce mNumerator/mDenominator to lowest terms. 19 | mNumerator = theNumerator / a; 20 | mDenominator = theDenominator / a; 21 | } 22 | } // namespace Sexy 23 | -------------------------------------------------------------------------------- /src/lawn/widget/ImitaterDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMITATERDIALOG_H__ 2 | #define __IMITATERDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | 6 | class ToolTipWidget; 7 | 8 | class ImitaterDialog : public LawnDialog { 9 | public: 10 | ToolTipWidget *mToolTip; 11 | SeedType mToolTipSeed; 12 | 13 | public: 14 | ImitaterDialog(); 15 | ~ImitaterDialog() override; 16 | 17 | SeedType SeedHitTest(int x, int y) const; 18 | void UpdateCursor(); 19 | void Update() override; 20 | /*inline*/ void GetSeedPosition(int theIndex, int &x, int &y) const; 21 | void Draw(Graphics *g) override; 22 | void ShowToolTip(); 23 | /*inline*/ void RemoveToolTip(); 24 | void MouseDown(int x, int y, int theClickCount) override; 25 | 26 | void MouseUp(int, int, int) override {} 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/framework/graphics/TriVertex.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRIVERTEX_H__ 2 | #define __TRIVERTEX_H__ 3 | 4 | namespace Sexy { 5 | /////////////////////////////////////////////////////////////////////////////// 6 | /////////////////////////////////////////////////////////////////////////////// 7 | class TriVertex { 8 | public: 9 | float x, y, u, v; 10 | uint32_t color; // ARGB (0 = use color specified in function call) 11 | 12 | public: 13 | TriVertex() { color = 0; } 14 | TriVertex(float theX, float theY) : x(theX), y(theY) { color = 0; } 15 | TriVertex(float theX, float theY, float theU, float theV) : x(theX), y(theY), u(theU), v(theV) { color = 0; } 16 | 17 | TriVertex(float theX, float theY, float theU, float theV, uint32_t theColor) 18 | : x(theX), y(theY), u(theU), v(theV), color(theColor) {} 19 | }; 20 | } // namespace Sexy 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/lawn/widget/ContinueDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONTINUEDIALOG_H__ 2 | #define __CONTINUEDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | 6 | class ContinueDialog : public LawnDialog { 7 | public: 8 | enum { ContinueDialog_Continue, ContinueDialog_NewGame }; 9 | 10 | public: 11 | DialogButton *mContinueButton; //+0x16C 12 | DialogButton *mNewGameButton; //+0x170 13 | 14 | public: 15 | ContinueDialog(LawnApp *theApp); 16 | ~ContinueDialog() override; 17 | 18 | int GetPreferredHeight(int theWidth) override; 19 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 20 | void AddedToManager(WidgetManager *theWidgetManager) override; 21 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 22 | void ButtonDepress(int theId) override; 23 | void RestartLoopingSounds() const; 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /CMakeSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "x64-Debug", 5 | "generator": "Ninja", 6 | "configurationType": "Debug", 7 | "inheritEnvironments": [ 8 | "msvc_x64_x64" 9 | ], 10 | "buildRoot": "${projectDir}\\out\\build\\${name}", 11 | "installRoot": "${projectDir}\\out\\install\\${name}", 12 | "cmakeCommandArgs": "", 13 | "buildCommandArgs": "", 14 | "ctestCommandArgs": "" 15 | }, 16 | { 17 | "name": "x64-Release", 18 | "generator": "Ninja", 19 | "configurationType": "Release", 20 | "inheritEnvironments": [ 21 | "msvc_x64_x64" 22 | ], 23 | "buildRoot": "${projectDir}\\out\\build\\${name}", 24 | "installRoot": "${projectDir}\\out\\install\\${name}", 25 | "cmakeCommandArgs": "", 26 | "buildCommandArgs": "", 27 | "ctestCommandArgs": "" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /cmake/embed_binary.cmake: -------------------------------------------------------------------------------- 1 | # https://stackoverflow.com/a/27206982 2 | # Creates C resources file from files in given list 3 | 4 | # bin: path to binary file 5 | # output: path to output file 6 | 7 | if (NOT EXISTS ${bin}) 8 | message(FATAL_ERROR "File ${bin} does not exist") 9 | endif () 10 | # Get short filename 11 | string(REGEX MATCH "([^/]+)$" filename ${bin}) 12 | # Replace filename spaces & extension separator for C compatibility 13 | string(REGEX REPLACE "\\.| |-" "_" filename ${filename}) 14 | # Read hex data from file 15 | file(READ ${bin} filedata HEX) 16 | if (filedata STREQUAL "") 17 | message(FATAL_ERROR "File ${bin} is empty") 18 | endif () 19 | # Convert hex data for C compatibility 20 | string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata}) 21 | file(WRITE ${output} "#include\n#include \nextern const uint8_t _binary_${filename}[] = {${filedata}};\nextern const size_t _binary_${filename}_size = sizeof(_binary_${filename});\n\n") -------------------------------------------------------------------------------- /src/lawn/widget/CheatDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHEATDIALOG_H__ 2 | #define __CHEATDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | #include "framework/widget/EditListener.h" 6 | #include "framework/widget/EditWidget.h" 7 | 8 | class CheatDialog : public LawnDialog, public EditListener { 9 | public: 10 | LawnApp *mApp; //+0x170 11 | EditWidget *mLevelEditWidget; //+0x174 12 | 13 | public: 14 | CheatDialog(LawnApp *theApp); 15 | ~CheatDialog() override; 16 | 17 | int GetPreferredHeight(int theWidth) override; 18 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 19 | void AddedToManager(WidgetManager *theWidgetManager) override; 20 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 21 | void Draw(Graphics *g) override; 22 | void EditWidgetText(int theId, const SexyString &theString) override; 23 | virtual bool AllowChar(int theId, SexyChar theChar); 24 | bool ApplyCheat() const; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/framework/sound/DummySoundInstance.h: -------------------------------------------------------------------------------- 1 | #ifndef __DUMMY_SOUND_INSTANCE_H__ 2 | #define __DUMMY_SOUND_INSTANCE_H__ 3 | 4 | #include "sound/SoundInstance.h" 5 | 6 | class DummySoundInstance : public Sexy::SoundInstance { 7 | public: 8 | void Release() override {} 9 | 10 | void SetBaseVolume(double) override {} 11 | 12 | void SetBasePan(int) override {} 13 | 14 | void AdjustPitch(double) override {} 15 | 16 | void SetVolume(double) override {} 17 | 18 | void SetPan(int) override {} //-hundredth db to +hundredth db = left to right 19 | 20 | int GetSoundPosition() override { return 0; } 21 | 22 | void SetSoundPosition(int /*thePosition*/) override {} 23 | 24 | bool Play(bool, bool) override { return true; } 25 | 26 | void Stop() override {} 27 | 28 | bool IsPlaying() override { return false; } 29 | bool IsReleased() override { return true; } 30 | double GetVolume() override { return 0; } 31 | }; 32 | 33 | #endif // __DUMMY_SOUND_INSTANCE_H__ 34 | -------------------------------------------------------------------------------- /src/framework/widget/Slider.h: -------------------------------------------------------------------------------- 1 | #ifndef __SLIDER_H__ 2 | #define __SLIDER_H__ 3 | 4 | #include "Widget.h" 5 | 6 | namespace Sexy { 7 | class SliderListener; 8 | 9 | class Slider : public Widget { 10 | public: 11 | SliderListener *mListener; 12 | double mVal; 13 | int mId; 14 | Image *mTrackImage; 15 | Image *mThumbImage; 16 | 17 | bool mDragging; 18 | int mRelX; 19 | int mRelY; 20 | 21 | bool mHorizontal; 22 | 23 | public: 24 | Slider(Image *theTrackImage, Image *theThumbImage, int theId, SliderListener *theListener); 25 | 26 | virtual void SetValue(double theValue); 27 | 28 | virtual bool HasTransparencies(); 29 | void Draw(Graphics *g) override; 30 | 31 | void MouseMove(int x, int y) override; 32 | void MouseDown(int x, int y, int theClickCount) override; 33 | void MouseDrag(int x, int y) override; 34 | void MouseUp(int x, int y) override; 35 | void MouseLeave() override; 36 | }; 37 | } // namespace Sexy 38 | 39 | #endif //__SLIDER_H__ 40 | -------------------------------------------------------------------------------- /src/framework/sound/SoundInstance.h: -------------------------------------------------------------------------------- 1 | #ifndef __SOUNDINSTANCE_H__ 2 | #define __SOUNDINSTANCE_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | class SoundInstance { 8 | public: 9 | SoundInstance() {} 10 | 11 | virtual ~SoundInstance() {} 12 | 13 | virtual void Release() = 0; 14 | 15 | virtual void SetBaseVolume(double theBaseVolume) = 0; 16 | virtual void SetBasePan(int theBasePan) = 0; 17 | 18 | virtual void AdjustPitch(double theNumSteps) = 0; 19 | 20 | virtual void SetVolume(double theVolume) = 0; 21 | virtual void SetPan(int thePosition) = 0; //-hundredth db to +hundredth db = left to right 22 | 23 | virtual int GetSoundPosition() = 0; 24 | virtual void SetSoundPosition(int thePosition) = 0; 25 | 26 | virtual bool Play(bool looping, bool autoRelease) = 0; 27 | virtual void Stop() = 0; 28 | virtual bool IsPlaying() = 0; 29 | virtual bool IsReleased() = 0; 30 | virtual double GetVolume() = 0; 31 | }; 32 | } // namespace Sexy 33 | 34 | #endif //__SOUNDINSTANCE_H__ 35 | -------------------------------------------------------------------------------- /src/lawn/CursorObject.h: -------------------------------------------------------------------------------- 1 | #ifndef __CURSOROBJECT_H__ 2 | #define __CURSOROBJECT_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "GameObject.h" 6 | 7 | class CursorObject : public GameObject { 8 | public: 9 | int mSeedBankIndex; //+0x24 10 | SeedType mType; //+0x28 11 | SeedType mImitaterType; //+0x2C 12 | CursorType mCursorType; //+0x30 13 | CoinID mCoinID; //+0x34 14 | PlantID mGlovePlantID; //+0x38 15 | PlantID mDuplicatorPlantID; //+0x3C 16 | PlantID mCobCannonPlantID; //+0x40 17 | int mHammerDownCounter; //+0x44 18 | ReanimationID mReanimCursorID; //+0x48 19 | 20 | public: 21 | CursorObject(); 22 | 23 | void Update(); 24 | void Draw(Graphics *g); 25 | void Die() const; 26 | }; 27 | 28 | class CursorPreview : public GameObject { 29 | public: 30 | int mGridX; 31 | int mGridY; 32 | 33 | public: 34 | CursorPreview(); 35 | 36 | void Update(); 37 | void Draw(Graphics *g); 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/framework/misc/PropertiesParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEXYAPPFRAMEWORK_NO_PROPERTIES_PARSER__ 2 | #ifndef __PROPERTIESPARSER_H__ 3 | #define __PROPERTIESPARSER_H__ 4 | 5 | #include "SexyAppBase.h" 6 | 7 | namespace Sexy { 8 | class XMLParser; 9 | 10 | class PropertiesParser { 11 | public: 12 | SexyAppBase *mApp; 13 | XMLParser *mXMLParser; 14 | SexyString mError; 15 | bool mHasFailed; 16 | 17 | protected: 18 | void Fail(const SexyString &theErrorText); 19 | 20 | bool ParseSingleElement(SexyString *theString); 21 | bool ParseStringArray(StringVector *theStringVector); 22 | bool ParseProperties(); 23 | bool DoParseProperties(); 24 | 25 | public: 26 | PropertiesParser(SexyAppBase *theApp); 27 | virtual ~PropertiesParser(); 28 | 29 | bool ParsePropertiesFile(const std::string &theFilename); 30 | bool ParsePropertiesBuffer(const Buffer &theBuffer); 31 | SexyString GetErrorText(); 32 | }; 33 | } // namespace Sexy 34 | 35 | #endif //__PROPERTIESPARSER_H__ 36 | 37 | #endif // __SEXYAPPFRAMEWORK_NO_PROPERTIES_PARSER__ 38 | -------------------------------------------------------------------------------- /src/lawn/widget/NewUserDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __NEWUSERDIALOG_H__ 2 | #define __NEWUSERDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | #include "framework/widget/EditListener.h" 6 | #include "widget/EditWidget.h" 7 | 8 | class NewUserDialog : public LawnDialog, public EditListener { 9 | public: 10 | LawnApp *mApp; //+0x170 11 | EditWidget *mNameEditWidget; //+0x174 12 | 13 | public: 14 | NewUserDialog(LawnApp *theApp, bool isRename); 15 | ~NewUserDialog() override; 16 | 17 | int GetPreferredHeight(int theWidth) override; 18 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 19 | void AddedToManager(WidgetManager *theWidgetManager) override; 20 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 21 | void Draw(Graphics *g) override; 22 | void EditWidgetText(int theId, const SexyString &theString) override; 23 | virtual bool AllowChar(int, SexyChar theChar); 24 | SexyString GetName() const; 25 | void SetName(const SexyString &theName) const; 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/compiler/hash.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "quick_sort.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace compiler { 11 | 12 | template constexpr T fnv_hash(const char *str, const T basis, const T prime) { 13 | size_t Val = basis; 14 | for (size_t Idx = 0; Idx < std::char_traits::length(str); ++Idx) { 15 | Val ^= static_cast(str[Idx]); 16 | Val *= prime; 17 | } 18 | return Val; 19 | } 20 | 21 | template constexpr T get_fnv_prime() {} 22 | template <> constexpr uint32_t get_fnv_prime() { return 16777619; } 23 | 24 | template <> constexpr uint64_t get_fnv_prime() { return 1099511628211; } 25 | 26 | constexpr auto hash(const char *str) { 27 | constexpr size_t FNV_hash_prime = get_fnv_prime(); 28 | constexpr size_t FNV_offset_basis = fnv_hash("chongo /\\../\\", (size_t)0, FNV_hash_prime); 29 | return fnv_hash(str, FNV_offset_basis, FNV_hash_prime); 30 | } 31 | 32 | } // namespace compiler 33 | -------------------------------------------------------------------------------- /src/framework/graphics/shaders/shader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(location = 0) out vec2 fragTexCoord; 4 | layout(location = 1) out vec4 fragColor; 5 | 6 | layout(push_constant) uniform constants { 7 | vec4 vertices[4]; 8 | uint colors[4]; 9 | bool isQuad; 10 | bool toFilter; 11 | } PushConstants; 12 | 13 | int indexBuffer[6] = { 14 | 0, 1, 2, 2, 1, 3 15 | }; 16 | 17 | vec4 unpackColor(uint color) { 18 | vec4 c = vec4((color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF, (color >> 24) & 0xFF)/255.0; 19 | return vec4(c.a * c.rgb, c.a); 20 | } 21 | 22 | void main() { 23 | //fragTexCoord = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2); 24 | uint index; 25 | if (PushConstants.isQuad) { 26 | index = indexBuffer[gl_VertexIndex]; 27 | } else { 28 | index = gl_VertexIndex; 29 | } 30 | 31 | vec4 vertex = PushConstants.vertices[index]; 32 | fragColor = unpackColor(PushConstants.colors[index]); 33 | 34 | fragTexCoord = vertex.zw; 35 | gl_Position = vec4(vertex.xy, 0.0, 1.0); 36 | } 37 | -------------------------------------------------------------------------------- /src/framework/misc/MTRand.h: -------------------------------------------------------------------------------- 1 | #ifndef __MTRAND_H__ 2 | #define __MTRAND_H__ 3 | 4 | #include 5 | 6 | namespace Sexy { 7 | #define MTRAND_N 624 8 | 9 | class MTRand { 10 | unsigned long mt[MTRAND_N]; /* the array for the state vector */ 11 | int mti; 12 | 13 | public: 14 | MTRand(const std::string &theSerialData); 15 | MTRand(unsigned long seed); 16 | MTRand(); 17 | 18 | void SRand(const std::string &theSerialData); 19 | void SRand(unsigned long seed); 20 | unsigned long NextNoAssert(); 21 | unsigned long Next(); 22 | unsigned long NextNoAssert(unsigned long range); 23 | unsigned long Next(unsigned long range); 24 | float NextNoAssert(float range); 25 | float Next(float range); 26 | 27 | std::string Serialize() const; 28 | 29 | static void SetRandAllowed(bool allowed); 30 | }; 31 | 32 | struct MTAutoDisallowRand { 33 | MTAutoDisallowRand() { MTRand::SetRandAllowed(false); } 34 | ~MTAutoDisallowRand() { MTRand::SetRandAllowed(true); } 35 | }; 36 | } // namespace Sexy 37 | 38 | #endif //__MTRAND_H__ 39 | -------------------------------------------------------------------------------- /src/res/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # RC 3 | ################################################################################ 4 | set(RC_OUTPUT_DIR ${CMAKE_BINARY_DIR}/res) 5 | file(GLOB RC_SRC 6 | ${CMAKE_CURRENT_SOURCE_DIR}/* 7 | ) 8 | 9 | list(REMOVE_ITEM RC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt") # Don't include self into the binary 10 | 11 | set(RC_DEPENDS "") 12 | foreach (RC_FILE ${RC_SRC}) 13 | get_filename_component(RC_FILE_NAME ${RC_FILE} NAME) 14 | add_custom_command( 15 | OUTPUT ${RC_OUTPUT_DIR}/${RC_FILE_NAME}.cpp 16 | COMMAND ${CMAKE_COMMAND} -Dbin="${RC_FILE}" -Doutput="${RC_OUTPUT_DIR}/${RC_FILE_NAME}.cpp" -P "${CMAKE_SOURCE_DIR}/cmake/embed_binary.cmake" 17 | DEPENDS ${RC_FILE} 18 | COMMENT "Converting ${RC_FILE_NAME} to C++" 19 | ) 20 | list(APPEND RC_DEPENDS ${RC_OUTPUT_DIR}/${RC_FILE_NAME}.cpp) 21 | endforeach () 22 | 23 | add_custom_target(rc DEPENDS ${RC_DEPENDS}) 24 | add_library(rc_lib STATIC ${RC_DEPENDS}) 25 | target_link_libraries(${PROJECT_NAME} PRIVATE rc_lib) -------------------------------------------------------------------------------- /src/framework/widget/Checkbox.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHECKBOX_H__ 2 | #define __CHECKBOX_H__ 3 | 4 | #include "Widget.h" 5 | 6 | namespace Sexy { 7 | class CheckboxListener; 8 | class Image; 9 | 10 | class Checkbox : public Widget { 11 | protected: 12 | CheckboxListener *mListener; 13 | 14 | public: 15 | int mId; 16 | 17 | bool mChecked; 18 | 19 | Image *mUncheckedImage; 20 | Image *mCheckedImage; 21 | 22 | Rect mCheckedRect; 23 | Rect mUncheckedRect; 24 | 25 | Color mOutlineColor; // These are only used if no image is specified 26 | Color mBkgColor; 27 | Color mCheckColor; 28 | 29 | public: 30 | virtual void SetChecked(bool checked, bool tellListener = true); 31 | virtual bool IsChecked(); 32 | 33 | void MouseDown(int x, int y, int theClickCount) override { Widget::MouseDown(x, y, theClickCount); } 34 | void MouseDown(int x, int y, int theBtnNum, int theClickCount) override; 35 | void Draw(Graphics *g) override; 36 | 37 | public: 38 | Checkbox(Image *theUncheckedImage, Image *theCheckedImage, int theId, CheckboxListener *theCheckboxListener); 39 | }; 40 | } // namespace Sexy 41 | 42 | #endif //__CHECKBOX_H__ 43 | -------------------------------------------------------------------------------- /src/todlib/FilterEffect.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILTEREFFECT_H__ 2 | #define __FILTEREFFECT_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace Sexy { 8 | class Image; 9 | // class MemoryImage; 10 | } // namespace Sexy 11 | 12 | using namespace Sexy; 13 | 14 | enum FilterEffect : int32_t { 15 | FILTER_EFFECT_NONE = -1, 16 | FILTER_EFFECT_WASHED_OUT, 17 | FILTER_EFFECT_LESS_WASHED_OUT, 18 | FILTER_EFFECT_WHITE, 19 | NUM_FILTER_EFFECTS 20 | }; 21 | 22 | using ImageFilterMap = std::unordered_map>; 23 | extern ImageFilterMap gFilterMap[FilterEffect::NUM_FILTER_EFFECTS]; 24 | 25 | void FilterEffectInitForApp(); 26 | void FilterEffectDisposeForApp(); 27 | // void FilterEffectDoLumSat(MemoryImage* theImage, float theLum, float theSat); 28 | ///*inline*/ void FilterEffectDoWashedOut(MemoryImage* theImage); 29 | ///*inline*/ void FilterEffectDoLessWashedOut(MemoryImage* theImage); 30 | // void FilterEffectDoWhite(MemoryImage* theImage); 31 | // MemoryImage* FilterEffectCreateImage(Image* theImage, FilterEffect theFilterEffect); 32 | Image *FilterEffectGetImage(Image *theImage, FilterEffect theFilterEffect); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/framework/graphics/Font.h: -------------------------------------------------------------------------------- 1 | #ifndef __FONT_H__ 2 | #define __FONT_H__ 3 | 4 | #include "Color.h" 5 | #include "framework/Common.h" 6 | #include "framework/misc/Rect.h" 7 | #include 8 | 9 | namespace Sexy { 10 | class Graphics; 11 | 12 | class _Font { 13 | public: 14 | int mAscent; 15 | int mAscentPadding; // How much space is above the avg uppercase char 16 | int mHeight; 17 | int mLineSpacingOffset; // This plus height should get added between lines 18 | public: 19 | _Font(); 20 | _Font(const _Font &theFont); 21 | virtual ~_Font(); 22 | 23 | virtual int GetAscent(); 24 | virtual int GetAscentPadding(); 25 | virtual int GetDescent(); 26 | virtual int GetHeight(); 27 | virtual int GetLineSpacingOffset(); 28 | virtual int GetLineSpacing(); 29 | virtual int StringWidth(const SexyString &theString); 30 | virtual int CharWidth(SexyChar theChar); 31 | virtual int CharWidthKern(SexyChar theChar, SexyChar thePrevChar); 32 | 33 | virtual void DrawString( 34 | Graphics *g, int theX, int theY, const SexyString &theString, const Color &theColor, const Rect &theClipRect 35 | ); 36 | 37 | virtual _Font *Duplicate() = 0; 38 | }; 39 | } // namespace Sexy 40 | 41 | #endif //__FONT_H__ 42 | -------------------------------------------------------------------------------- /src/framework/graphics/Font.cpp: -------------------------------------------------------------------------------- 1 | #include "Font.h" 2 | #include "Image.h" 3 | 4 | using namespace Sexy; 5 | 6 | _Font::_Font() { 7 | mAscent = 0; 8 | mAscentPadding = 0; 9 | mHeight = 0; 10 | mLineSpacingOffset = 0; 11 | } 12 | 13 | _Font::_Font(const _Font &theFont) 14 | : mAscent(theFont.mAscent), mAscentPadding(theFont.mAscentPadding), mHeight(theFont.mHeight), 15 | mLineSpacingOffset(theFont.mLineSpacingOffset) {} 16 | 17 | _Font::~_Font() {} 18 | 19 | int _Font::GetAscent() { return mAscent; } 20 | 21 | int _Font::GetAscentPadding() { return mAscentPadding; } 22 | 23 | int _Font::GetDescent() { return mHeight - mAscent; } 24 | 25 | int _Font::GetHeight() { return mHeight; } 26 | 27 | int _Font::GetLineSpacingOffset() { return mLineSpacingOffset; } 28 | 29 | int _Font::GetLineSpacing() { return mHeight + mLineSpacingOffset; } 30 | 31 | int _Font::StringWidth(const SexyString &) { return 0; } 32 | 33 | int _Font::CharWidth(SexyChar theChar) { 34 | const SexyString aString(1, theChar); 35 | return StringWidth(aString); 36 | } 37 | 38 | int _Font::CharWidthKern(SexyChar theChar, SexyChar) { return CharWidth(theChar); } 39 | 40 | void _Font::DrawString(Graphics *, int, int, const SexyString &, const Color &, const Rect &) {} 41 | -------------------------------------------------------------------------------- /src/lawn/system/TypingCheck.cpp: -------------------------------------------------------------------------------- 1 | #include "TypingCheck.h" 2 | using namespace Sexy; 3 | 4 | // 0x51C470 5 | TypingCheck::TypingCheck(const std::string &thePhrase) { SetPhrase(thePhrase); } 6 | 7 | // 0x51C4D0 8 | void TypingCheck::SetPhrase(const std::string &thePhrase) { 9 | for (size_t i = 0; i < thePhrase.size(); i++) 10 | AddChar(thePhrase[i]); 11 | } 12 | 13 | void TypingCheck::AddKeyCode(Sexy::KeyCode theKeyCode) { mPhrase.append(1, static_cast(theKeyCode)); } 14 | 15 | // 0x51C510 16 | void TypingCheck::AddChar(char theChar) { 17 | theChar = static_cast(tolower(theChar)); 18 | const std::string aCharString{theChar}; 19 | AddKeyCode(GetKeyCodeFromName(aCharString)); 20 | } 21 | 22 | bool TypingCheck::Check() { 23 | if (mRecentTyping.compare(mPhrase) == 0) { 24 | mRecentTyping.clear(); 25 | return true; 26 | } 27 | return false; 28 | } 29 | 30 | // 0x51C5A0 31 | bool TypingCheck::Check(Sexy::KeyCode theKeyCode) { 32 | mRecentTyping.append(1, static_cast(theKeyCode)); 33 | const size_t aLength = mPhrase.size(); 34 | if (aLength == 0) return false; 35 | 36 | if (mRecentTyping.size() > aLength) mRecentTyping = mRecentTyping.substr(1, aLength); 37 | 38 | return Check(); 39 | } 40 | -------------------------------------------------------------------------------- /src/framework/graphics/Color.h: -------------------------------------------------------------------------------- 1 | #ifndef __COLOR_H__ 2 | #define __COLOR_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | #pragma pack(push, 1) 8 | struct SexyRGBA { 9 | unsigned char b, g, r, a; 10 | }; 11 | #pragma pack(pop) 12 | 13 | class Color { 14 | public: 15 | int mRed; 16 | int mGreen; 17 | int mBlue; 18 | int mAlpha; 19 | 20 | static Color Black; 21 | static Color White; 22 | 23 | public: 24 | Color(); 25 | explicit Color(int theColor); 26 | Color(const int theColor, const int theAlpha); 27 | Color(const int theRed, const int theGreen, const int theBlue, const int theAlpha = 0xFF); 28 | explicit Color(const SexyRGBA &theColor); 29 | explicit Color(const uint8_t *theElements); 30 | explicit Color(const int *theElements); 31 | 32 | int GetRed() const; 33 | int GetGreen() const; 34 | int GetBlue() const; 35 | int GetAlpha() const; 36 | uint32_t ToInt() const; 37 | SexyRGBA ToRGBA() const; 38 | 39 | int &operator[](int theIdx); 40 | int operator[](int theIdx) const; 41 | }; 42 | 43 | bool operator==(const Color &theColor1, const Color &theColor2); 44 | bool operator!=(const Color &theColor1, const Color &theColor2); 45 | } // namespace Sexy 46 | 47 | #endif //__COLOR_H__ 48 | -------------------------------------------------------------------------------- /src/lawn/system/PoolEffect.h: -------------------------------------------------------------------------------- 1 | #ifndef __POOLEFFECT_H__ 2 | #define __POOLEFFECT_H__ 3 | 4 | #include "framework/graphics/Image.h" 5 | #include "graphics/VkCommon.h" 6 | #include "graphics/VkImage.h" 7 | #include 8 | #include 9 | 10 | constexpr const int CAUSTIC_IMAGE_WIDTH = 128; 11 | constexpr const int CAUSTIC_IMAGE_HEIGHT = 64; 12 | constexpr const size_t CAUSTIC_SIZE_BYTES = 13 | CAUSTIC_IMAGE_WIDTH * CAUSTIC_IMAGE_HEIGHT * SCALE * SCALE * sizeof(uint32_t); 14 | 15 | class LawnApp; 16 | 17 | class PoolEffect { 18 | public: 19 | std::unique_ptr mCausticGrayscaleImage; 20 | std::array, CAUSTIC_IMAGE_HEIGHT> mMemCausticImage; 21 | std::unique_ptr mCausticImage; 22 | 23 | VkBuffer mStagingBuffer; 24 | VkDeviceMemory mStagingBufferMemory; 25 | 26 | LawnApp *mApp; 27 | int mPoolCounter; 28 | 29 | public: 30 | void PoolEffectInitialize(); 31 | void PoolEffectDispose(); 32 | void PoolEffectDraw(Sexy::Graphics *g, bool theIsNight); 33 | void UpdateWaterEffect(); 34 | unsigned int BilinearLookupFixedPoint(unsigned int u, unsigned int v) const; 35 | // unsigned int BilinearLookup(float u, float v); 36 | void PoolEffectUpdate(); 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/framework/widget/HyperlinkWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "HyperlinkWidget.h" 2 | #include "WidgetManager.h" 3 | #include "graphics/Graphics.h" 4 | #include "graphics/ImageFont.h" 5 | 6 | using namespace Sexy; 7 | 8 | HyperlinkWidget::HyperlinkWidget(int theId, ButtonListener *theButtonListener) 9 | : ButtonWidget(theId, theButtonListener), mColor(255, 255, 255), mOverColor(255, 255, 255) { 10 | mDoFinger = true; 11 | mUnderlineOffset = 3; 12 | mUnderlineSize = 1; 13 | } 14 | 15 | void HyperlinkWidget::Draw(Graphics *g) { 16 | /* FIXME 17 | if (mFont == NULL) 18 | mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 10); //baz changed 19 | */ 20 | 21 | int aFontX = (mWidth - mFont->StringWidth(mLabel)) / 2; 22 | int aFontY = (mHeight + mFont->GetAscent()) / 2 - 1; 23 | 24 | if (mIsOver) g->SetColor(mOverColor); 25 | else g->SetColor(mColor); 26 | 27 | g->SetFont(mFont); 28 | g->DrawString(mLabel, aFontX, aFontY); 29 | 30 | for (int i = 0; i < mUnderlineSize; i++) 31 | g->FillRect(aFontX, aFontY + mUnderlineOffset + i, mFont->StringWidth(mLabel), 1); 32 | } 33 | 34 | void HyperlinkWidget::MouseEnter() { 35 | ButtonWidget::MouseEnter(); 36 | 37 | MarkDirtyFull(); 38 | } 39 | 40 | void HyperlinkWidget::MouseLeave() { 41 | ButtonWidget::MouseLeave(); 42 | 43 | MarkDirtyFull(); 44 | } 45 | -------------------------------------------------------------------------------- /src/framework/sound/DummySoundManager.h: -------------------------------------------------------------------------------- 1 | #ifndef __DUMMY_SOUND_MANAGER_H__ 2 | #define __DUMMY_SOUND_MANAGER_H__ 3 | 4 | #include "DummySoundInstance.h" 5 | #include "SoundManager.h" 6 | 7 | class DummySoundManager : public Sexy::SoundManager { 8 | public: 9 | bool Initialized() override { return true; } 10 | 11 | bool LoadSound(unsigned int, const std::string &) override { return true; } 12 | int LoadSound(const std::string &) override { return 0; } 13 | 14 | void ReleaseSound(unsigned int) override {} 15 | 16 | void SetVolume(double) override {} 17 | 18 | bool SetBaseVolume(unsigned int, double) override { return 0; } 19 | bool SetBasePan(unsigned int, int) override { return 0; } 20 | 21 | Sexy::SoundInstance *GetSoundInstance(unsigned int) override { return &dummy; } 22 | 23 | void ReleaseSounds() override {} 24 | 25 | void ReleaseChannels() override {} 26 | 27 | double GetMasterVolume() override { return 0; } 28 | 29 | void SetMasterVolume(double) override {} 30 | 31 | void Flush() override {} 32 | 33 | // virtual void SetCooperativeWindow(HWND theHWnd) {} 34 | void StopAllSounds() override {} 35 | 36 | int GetFreeSoundId() override { return 0; } 37 | int GetNumSounds() override { return 0; } 38 | 39 | private: 40 | DummySoundInstance dummy; 41 | }; 42 | 43 | #endif // __DUMMY_SOUND_MANAGER_H__ 44 | -------------------------------------------------------------------------------- /src/framework/sound/DummyMusicInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef __DUMMY_MUSIC_INTERFACE_H__ 2 | #define __DUMMY_MUSIC_INTERFACE_H__ 3 | 4 | #include "MusicInterface.h" 5 | 6 | using namespace Sexy; 7 | 8 | class DummyMusicInterface : public MusicInterface { 9 | public: 10 | DummyMusicInterface() {} 11 | 12 | ~DummyMusicInterface() override{}; 13 | 14 | bool LoadMusic(int, const std::string &) override { return false; } 15 | 16 | void PlayMusic(int, int, bool) override {} 17 | 18 | void StopMusic(int) override {} 19 | 20 | void PauseMusic(int) override {} 21 | 22 | void ResumeMusic(int) override {} 23 | 24 | void StopAllMusic() override {} 25 | 26 | void UnloadMusic(int) override {} 27 | 28 | void UnloadAllMusic() override {} 29 | 30 | void PauseAllMusic() override {} 31 | 32 | void ResumeAllMusic() override {} 33 | 34 | void FadeIn(int, int, double, bool) override {} 35 | 36 | void FadeOut(int, bool, double) override {} 37 | 38 | void FadeOutAll(bool, double) override {} 39 | 40 | void SetSongVolume(int, double) override {} 41 | 42 | void SetSongMaxVolume(int, double) override {} 43 | 44 | bool IsPlaying(int) override { return false; }; 45 | 46 | void SetVolume(double) override {} 47 | 48 | void SetMusicAmplify(int, double) override {} 49 | 50 | void Update() override {} 51 | }; 52 | 53 | #endif // __DUMMY_MUSIC_INTERFACE_H__ 54 | -------------------------------------------------------------------------------- /src/lawn/ToolTipWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOLTIPWIDGET_H__ 2 | #define __TOOLTIPWIDGET_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | class Graphics; 8 | } 9 | 10 | class ToolTipWidget { 11 | public: 12 | SexyString mTitle; //+0x0 13 | SexyString mLabel; //+0x1C 14 | SexyString mWarningText; //+0x28 15 | int mX; //+0x54 16 | int mY; //+0x58 17 | int mWidth; //+0x5C 18 | int mHeight; //+0x60 19 | bool mVisible; //+0x64 20 | bool mCenter; //+0x65 21 | int mMinLeft; //+0x68 22 | int mMaxBottom; //+0x6C 23 | int mGetsLinesWidth; //+0x70 24 | int mWarningFlashCounter; //+0x74 25 | 26 | public: 27 | ToolTipWidget(); 28 | 29 | void Draw(Sexy::Graphics *g); 30 | void SetLabel(const SexyString &theLabel); 31 | void SetTitle(const SexyString &theTitle); 32 | void SetWarningText(const SexyString &theWarningText); 33 | void CalculateSize(); 34 | void GetLines(std::vector &theLines) const; 35 | inline void FlashWarning() { mWarningFlashCounter = 70; } 36 | inline void Update() { 37 | if (mWarningFlashCounter > 0) mWarningFlashCounter--; 38 | } 39 | 40 | inline void SetPosition(int theX, int theY) { 41 | mX = theX; 42 | mY = theY; 43 | } 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/framework/sound/SoundManager.h: -------------------------------------------------------------------------------- 1 | #ifndef __SOUNDMANAGER_H__ 2 | #define __SOUNDMANAGER_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | class SoundInstance; 8 | 9 | #define MAX_SOURCE_SOUNDS 256 10 | #define MAX_CHANNELS 32 11 | 12 | class SoundManager { 13 | public: 14 | SoundManager() {} 15 | 16 | virtual ~SoundManager() {} 17 | 18 | virtual bool Initialized() = 0; 19 | 20 | virtual bool LoadSound(unsigned int theSfxID, const std::string &theFilename) = 0; 21 | virtual int LoadSound(const std::string &theFilename) = 0; 22 | virtual void ReleaseSound(unsigned int theSfxID) = 0; 23 | 24 | virtual void SetVolume(double theVolume) = 0; 25 | virtual bool SetBaseVolume(unsigned int theSfxID, double theBaseVolume) = 0; 26 | virtual bool SetBasePan(unsigned int theSfxID, int theBasePan) = 0; 27 | 28 | virtual SoundInstance *GetSoundInstance(unsigned int theSfxID) = 0; 29 | 30 | virtual void ReleaseSounds() = 0; 31 | virtual void ReleaseChannels() = 0; 32 | 33 | virtual double GetMasterVolume() = 0; 34 | virtual void SetMasterVolume(double theVolume) = 0; 35 | 36 | virtual void Flush() = 0; 37 | // virtual void SetCooperativeWindow(HWND theHWnd) = 0; 38 | virtual void StopAllSounds() = 0; 39 | virtual int GetFreeSoundId() = 0; 40 | virtual int GetNumSounds() = 0; 41 | }; 42 | } // namespace Sexy 43 | 44 | #endif //__SOUNDMANAGER_H__ 45 | -------------------------------------------------------------------------------- /src/framework/sound/BassSoundInstance.h: -------------------------------------------------------------------------------- 1 | #ifndef __BASS_SOUND_INSTANCE_H__ 2 | #define __BASS_SOUND_INSTANCE_H__ 3 | 4 | #include "SoundInstance.h" 5 | #include 6 | 7 | namespace Sexy { 8 | class BassSoundManager; 9 | 10 | class BassSoundInstance : public Sexy::SoundInstance { 11 | public: 12 | BassSoundInstance(HSAMPLE theSourceSound); 13 | ~BassSoundInstance() override; 14 | void Release() override; 15 | 16 | void SetBaseVolume(double /*theBaseVolume*/) override {} 17 | 18 | void SetBasePan(int /*theBasePan*/) override {} 19 | 20 | void SetVolume(double theVolume) override; 21 | void SetPan(int thePosition) override; //-hundredth db to +hundredth db = left to right 22 | void AdjustPitch(double theNumSteps) override; 23 | 24 | int GetSoundPosition() override; 25 | void SetSoundPosition(int thePosition) override; 26 | 27 | bool Play(bool looping, bool autoRelease) override; 28 | void Stop() override; 29 | bool IsPlaying() override; 30 | bool IsReleased() override; 31 | double GetVolume() override; 32 | 33 | private: 34 | void RehupVolume() const; 35 | void RehupPan() const; 36 | 37 | HSAMPLE mSample; 38 | HCHANNEL mChannel; 39 | 40 | bool mAutoRelease = false; 41 | bool mHasPlayed = false; 42 | bool mReleased = false; 43 | 44 | int mPan = 0; 45 | double mVolume = 1.0; 46 | 47 | DWORD mDefaultFrequency = 44100; 48 | }; 49 | } // namespace Sexy 50 | 51 | #endif // __BASS_SOUND_INSTANCE_H__ 52 | -------------------------------------------------------------------------------- /src/lawn/LawnMower.h: -------------------------------------------------------------------------------- 1 | #ifndef __LAWNMOWER_H__ 2 | #define __LAWNMOWER_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/misc/Rect.h" 6 | 7 | class LawnApp; 8 | class Board; 9 | class Zombie; 10 | 11 | namespace Sexy { 12 | class Graphics; 13 | }; 14 | 15 | using namespace Sexy; 16 | 17 | class LawnMower { 18 | public: 19 | LawnApp *mApp; //+0x0 20 | Board *mBoard; //+0x4 21 | float mPosX; //+0x8 22 | float mPosY; //+0xC 23 | int mRenderOrder; //+0x10 24 | int mRow; //+0x14 25 | int mAnimTicksPerFrame; //+0x18 26 | ReanimationID mReanimID; //+0x1C 27 | int mChompCounter; //+0x20 28 | int mRollingInCounter; //+0x24 29 | int mSquishedCounter; //+0x28 30 | LawnMowerState mMowerState; //+0x2C 31 | bool mDead; //+0x30 32 | bool mVisible; //+0x31 33 | LawnMowerType mMowerType; //+0x34 34 | float mAltitude; //+0x38 35 | MowerHeight mMowerHeight; //+0x3C 36 | int mLastPortalX; //+0x40 37 | 38 | public: 39 | void LawnMowerInitialize(int theRow); 40 | void StartMower(); 41 | void Update(); 42 | void Draw(Graphics *g) const; 43 | void Die(); 44 | Rect GetLawnMowerAttackRect(); 45 | void UpdatePool(); 46 | void MowZombie(Zombie *theZombie); 47 | void SquishMower(); 48 | /*inline*/ void EnableSuperMower(bool theEnable); 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/lawn/system/ProfileMgr.h: -------------------------------------------------------------------------------- 1 | #ifndef __PROFILEMGR_H__ 2 | #define __PROFILEMGR_H__ 3 | 4 | #include "framework/Common.h" 5 | #include 6 | #include 7 | 8 | class DataSync; 9 | class PlayerInfo; 10 | using ProfilePair = std::pair; 11 | using ProfileMap = std::map; 12 | 13 | class ProfileMgr { 14 | protected: 15 | ProfileMap mProfileMap; //+0x4 16 | unsigned long mNextProfileId; //+0x10 17 | unsigned long mNextProfileUseSeq; //+0x14 18 | 19 | protected: 20 | void SyncState(DataSync &theSync); 21 | void DeleteOldestProfile(); 22 | inline void DeleteOldProfiles() { 23 | while (mProfileMap.size() > 200) 24 | DeleteOldestProfile(); 25 | } 26 | 27 | public: 28 | bool DeleteProfile(const SexyString &theName); 29 | 30 | protected: 31 | /*inline*/ void DeleteProfile(ProfileMap::iterator theProfile); 32 | 33 | public: 34 | ProfileMgr() { Clear(); } // 0x46A6E0 35 | virtual ~ProfileMgr() { ; } // 0x46A780 36 | 37 | /*inline*/ void Clear(); 38 | void Load(); 39 | void Save(); 40 | inline int GetNumProfiles() const { return mProfileMap.size(); } 41 | PlayerInfo *GetProfile(const SexyString &theName); 42 | PlayerInfo *AddProfile(const SexyString &theName); 43 | PlayerInfo *GetAnyProfile(); 44 | bool RenameProfile(const SexyString &theOldName, const SexyString &theNewName); 45 | inline ProfileMap &GetProfileMap() { return mProfileMap; } 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/framework/sound/MusicInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef __MUSICINTERFACE_H__ 2 | #define __MUSICINTERFACE_H__ 3 | 4 | #include 5 | 6 | namespace Sexy { 7 | class MusicInterface { 8 | public: 9 | MusicInterface() {} 10 | 11 | virtual ~MusicInterface() {} 12 | 13 | virtual bool LoadMusic(int theSongId, const std::string &theFileName) = 0; 14 | virtual void PlayMusic(int theSongId, int theOffset = 0, bool noLoop = false) = 0; 15 | virtual void StopMusic(int theSongId) = 0; 16 | virtual void PauseMusic(int theSongId) = 0; 17 | virtual void ResumeMusic(int theSongId) = 0; 18 | virtual void StopAllMusic() = 0; 19 | 20 | virtual void UnloadMusic(int theSongId) = 0; 21 | virtual void UnloadAllMusic() = 0; 22 | virtual void PauseAllMusic() = 0; 23 | virtual void ResumeAllMusic() = 0; 24 | 25 | virtual void FadeIn(int theSongId, int theOffset = -1, double theSpeed = 0.002, bool noLoop = false) = 0; 26 | virtual void FadeOut(int theSongId, bool stopSong = true, double theSpeed = 0.004) = 0; 27 | virtual void FadeOutAll(bool stopSong = true, double theSpeed = 0.004) = 0; 28 | virtual void SetSongVolume(int theSongId, double theVolume) = 0; 29 | virtual void SetSongMaxVolume(int theSongId, double theMaxVolume) = 0; 30 | virtual bool IsPlaying(int theSongId) = 0; 31 | 32 | virtual void SetVolume(double theVolume) = 0; 33 | virtual void SetMusicAmplify(int theSongId, double theAmp) = 0; 34 | virtual void Update() = 0; 35 | }; 36 | } // namespace Sexy 37 | 38 | #endif //__MUSICINTERFACE_H__ 39 | -------------------------------------------------------------------------------- /src/framework/misc/Ratio.h: -------------------------------------------------------------------------------- 1 | #ifndef __RATIO_H__ 2 | #define __RATIO_H__ 3 | 4 | namespace Sexy { 5 | struct Ratio { 6 | Ratio(); 7 | Ratio(int theNumerator, int theDenominator); 8 | void Set(int theNumerator, int theDenominator); 9 | bool operator==(const Ratio &theRatio) const; 10 | bool operator!=(const Ratio &theRatio) const; 11 | bool operator<(const Ratio &theRatio) const; 12 | int operator*(int theInt) const; 13 | int operator/(int theInt) const; 14 | int mNumerator; 15 | int mDenominator; 16 | }; 17 | 18 | inline bool Ratio::operator==(const Ratio &theRatio) const { 19 | return mNumerator == theRatio.mNumerator && mDenominator == theRatio.mDenominator; 20 | } 21 | 22 | inline bool Ratio::operator!=(const Ratio &theRatio) const { return !(*this == theRatio); } 23 | 24 | inline bool Ratio::operator<(const Ratio &theRatio) const { 25 | return (mNumerator * theRatio.mDenominator / mDenominator < theRatio.mNumerator) || 26 | (mNumerator < theRatio.mNumerator * mDenominator / theRatio.mDenominator); 27 | } 28 | 29 | inline int Ratio::operator*(int theInt) const { return theInt * mNumerator / mDenominator; } 30 | 31 | inline int Ratio::operator/(int theInt) const { return theInt * mDenominator / mNumerator; } 32 | 33 | inline int operator*(int theInt, const Ratio &theRatio) { return theInt * theRatio.mNumerator / theRatio.mDenominator; } 34 | 35 | inline int operator/(int theInt, const Ratio &theRatio) { return theInt * theRatio.mDenominator / theRatio.mNumerator; } 36 | } // namespace Sexy 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/framework/imagelib/ImageLib.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMAGELIB_H__ 2 | #define __IMAGELIB_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "framework/misc/ResourceManager.h" 9 | 10 | namespace ImageLib { 11 | class Image { 12 | public: 13 | int mWidth = 0; 14 | int mHeight = 0; 15 | std::unique_ptr mBits = nullptr; 16 | 17 | Image(int width, int height) 18 | : mWidth(width), mHeight(height), mBits(std::make_unique(mWidth * mHeight)) { 19 | memset(mBits.get(), 0, mWidth * mHeight * sizeof(uint32_t)); 20 | } 21 | 22 | Image(int width, int height, std::unique_ptr bits) 23 | : mWidth(width), mHeight(height), mBits(std::move(bits)) {} 24 | }; 25 | 26 | bool WriteJPEGImage(const std::string &theFileName, const Image *theImage); 27 | bool WritePNGImage(const std::string &theFileName, const Image *theImage); 28 | bool WriteTGAImage(const std::string &theFileName, const Image *theImage); 29 | bool WriteBMPImage(const std::string &theFileName, const Image *theImage); 30 | extern int gAlphaComposeColor; 31 | extern bool gAutoLoadAlpha; 32 | extern bool gIgnoreJPEG2000Alpha; 33 | // I've noticed alpha in jpeg2000's that shouldn't have alpha so this defaults to true 34 | 35 | std::unique_ptr GetImage(const Sexy::ResourceManager::ImageRes &theFilename, bool lookForAlphaImage); 36 | 37 | // void InitJPEG2000(); 38 | // void CloseJPEG2000(); 39 | // void SetJ2KCodecKey(const std::string& theKey); 40 | } // namespace ImageLib 41 | 42 | #endif //__IMAGELIB_H__ 43 | -------------------------------------------------------------------------------- /src/lawn/widget/UserDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __USERDIALOG_H__ 2 | #define __USERDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | #include "framework/widget/EditListener.h" 6 | #include "framework/widget/ListListener.h" 7 | 8 | namespace Sexy { 9 | class ListWidget; 10 | }; 11 | 12 | class UserDialog : public LawnDialog, public ListListener, public EditListener { 13 | protected: 14 | enum { UserDialog_RenameUser, UserDialog_DeleteUser }; 15 | 16 | public: 17 | ListWidget *mUserList; //+0x174 18 | DialogButton *mRenameButton; //+0x178 19 | DialogButton *mDeleteButton; //+0x17C 20 | int mNumUsers; //+0x180 21 | 22 | public: 23 | UserDialog(LawnApp *theApp); 24 | ~UserDialog() override; 25 | 26 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 27 | int GetPreferredHeight(int theWidth) override; 28 | void AddedToManager(WidgetManager *theWidgetManager) override; 29 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 30 | void ListClicked(int theId, int theIdx, int theClickCount) override; 31 | 32 | void ListClosed(int) override {} 33 | 34 | void ListHiliteChanged(int, int, int) override {} 35 | 36 | void ButtonDepress(int theId) override; 37 | void EditWidgetText(int theId, const SexyString &theString) override; 38 | virtual bool AllowChar(int theId, SexyChar theChar); 39 | void Draw(Graphics *g) override; 40 | void FinishDeleteUser(); 41 | void FinishRenameUser(const SexyString &theNewName) const; 42 | SexyString GetSelName() const; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/framework/graphics/VkInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef __VK_INTERFACE_H__ 2 | #define __VK_INTERFACE_H__ 3 | 4 | #include "framework/graphics/WindowInterface.h" 5 | #include "framework/widget/WidgetManager.h" 6 | 7 | namespace Vk { 8 | class VkInterface : public WindowInterface { 9 | public: 10 | VkInterface(int width, int height, WidgetManager *mWidgetManager, bool fullscreen); 11 | ~VkInterface(); 12 | 13 | int GetRefreshRate(); 14 | static void UpdateWindowOptions(const int width, const int height, const bool fullscreen); 15 | static Image *GetScreenImage(); 16 | static int 17 | CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, const void *pvANDPlane, const void *pvXORPlane); 18 | static void EnforceCursor(); 19 | static void ShowWindow(); 20 | void PollEvents(); 21 | static bool IsFocused(); 22 | static void RehupFocus(); 23 | bool ShouldClose() const; 24 | static void ReleaseMouseCapture(); 25 | static void Draw(); 26 | 27 | private: 28 | bool windowShouldClose = false; 29 | static void framebufferResizeCallback(); 30 | static void windowFocusCallback(bool focused); 31 | static void cursorPositionCallback(double xpos, double ypos); 32 | static void mouseWheelCallback(double xoffset, double yoffset); 33 | void mouseButtonCallback(int button, int state, int clicks) const; 34 | static void keyCallback(uint32_t key, uint8_t state); 35 | static void charCallback(char codepoint[32]); 36 | static void cursorEnterCallback(int entered); 37 | void windowCloseCallback(); 38 | }; 39 | } // namespace Vk 40 | 41 | #endif // __VK_INTERFACE_H__ 42 | -------------------------------------------------------------------------------- /src/framework/misc/Flags.h: -------------------------------------------------------------------------------- 1 | #ifndef __FLAGS_H__ 2 | #define __FLAGS_H__ 3 | 4 | namespace Sexy { 5 | class FlagsMod { 6 | public: 7 | int mAddFlags; 8 | int mRemoveFlags; 9 | 10 | public: 11 | FlagsMod() { 12 | mAddFlags = 0; 13 | mRemoveFlags = 0; 14 | } 15 | }; 16 | 17 | inline void ModFlags(int &theFlags, const FlagsMod &theFlagMod) { 18 | theFlags = (theFlags | theFlagMod.mAddFlags) & ~theFlagMod.mRemoveFlags; 19 | } 20 | 21 | inline int GetModFlags(int theFlags, const FlagsMod &theFlagMod) { 22 | return (theFlags | theFlagMod.mAddFlags) & ~theFlagMod.mRemoveFlags; 23 | } 24 | 25 | class ModalFlags { 26 | public: 27 | int mOverFlags; 28 | int mUnderFlags; 29 | bool mIsOver; 30 | 31 | public: 32 | void ModFlags(const FlagsMod &theFlagsMod) { 33 | Sexy::ModFlags(mOverFlags, theFlagsMod); 34 | Sexy::ModFlags(mUnderFlags, theFlagsMod); 35 | } 36 | 37 | int GetFlags() { return mIsOver ? mOverFlags : mUnderFlags; } 38 | }; 39 | 40 | class AutoModalFlags { 41 | public: 42 | ModalFlags *mModalFlags; 43 | int mOldOverFlags; 44 | int mOldUnderFlags; 45 | 46 | public: 47 | AutoModalFlags(ModalFlags *theModalFlags, const FlagsMod &theFlagMod) { 48 | mModalFlags = theModalFlags; 49 | mOldOverFlags = theModalFlags->mOverFlags; 50 | mOldUnderFlags = theModalFlags->mUnderFlags; 51 | theModalFlags->ModFlags(theFlagMod); 52 | } 53 | 54 | ~AutoModalFlags() { 55 | mModalFlags->mOverFlags = mOldOverFlags; 56 | mModalFlags->mUnderFlags = mOldUnderFlags; 57 | } 58 | }; 59 | } // namespace Sexy 60 | 61 | #endif //__FLAGS_H__ 62 | -------------------------------------------------------------------------------- /src/lawn/MessageWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESSAGEWIDGET_H__ 2 | #define __MESSAGEWIDGET_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "LawnApp.h" 6 | #include "framework/Common.h" 7 | 8 | #define MAX_MESSAGE_LENGTH 128 9 | #define MAX_REANIM_LINES 5 10 | 11 | class LawnApp; 12 | 13 | namespace Sexy { 14 | class _Font; 15 | class Graphics; 16 | } // namespace Sexy 17 | 18 | class MessageWidget { 19 | public: 20 | LawnApp *mApp; //+0x0 21 | SexyChar mLabel[MAX_MESSAGE_LENGTH]; //+0x4 22 | int mDisplayTime; //+0x84 23 | int mDuration; //+0x88 24 | MessageStyle mMessageStyle; //+0x8C 25 | ReanimationID mTextReanimID[MAX_MESSAGE_LENGTH]; //+0x90 26 | ReanimationType mReanimType; //+0x290 27 | int mSlideOffTime; //+0x294 28 | SexyChar mLabelNext[MAX_MESSAGE_LENGTH]; //+0x298 29 | MessageStyle mMessageStyleNext; //+0x318 30 | 31 | public: 32 | MessageWidget(LawnApp *theApp); 33 | ~MessageWidget() { ClearReanim(); } 34 | 35 | /*inline*/ void SetLabel(const SexyString &theNewLabel, MessageStyle theMessageStyle); 36 | void Update(); 37 | void Draw(Sexy::Graphics *g); 38 | void ClearReanim(); 39 | /*inline*/ void ClearLabel(); 40 | inline bool IsBeingDisplayed() { return mDuration != 0; } 41 | /*inline*/ _Font *GetFont(); 42 | void DrawReanimatedText(Sexy::Graphics *g, Sexy::_Font *theFont, const Sexy::Color &theColor, float thePosY) const; 43 | void LayoutReanimText(); 44 | }; 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #if defined(_WIN32) && !defined(_DEBUG) 2 | #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") 3 | #endif 4 | 5 | #ifdef __ANDROID__ 6 | #include "SDL.h" 7 | #endif 8 | 9 | #include "LawnApp.h" 10 | #include "Resources.h" 11 | #include "todlib/TodStringFile.h" 12 | using namespace Sexy; 13 | 14 | bool (*gAppCloseRequest)(); //[0x69E6A0] 15 | bool (*gAppHasUsedCheatKeys)(); //[0x69E6A4] 16 | SexyString (*gGetCurrentLevelName)(); 17 | 18 | // 0x44E8F0 19 | int main(const int argc, char *argv[]) { 20 | TodStringListSetColors(gLawnStringFormats, gLawnStringFormatCount); 21 | gGetCurrentLevelName = LawnGetCurrentLevelName; 22 | gAppCloseRequest = LawnGetCloseRequest; 23 | gAppHasUsedCheatKeys = LawnHasUsedCheatKeys; 24 | gExtractResourcesByName = Sexy::ExtractResourcesByName; 25 | 26 | #ifdef __ANDROID__ 27 | SetAppDataFolder(SDL_AndroidGetExternalStoragePath()); 28 | #endif 29 | 30 | TodLogger aTodLogger{}; 31 | 32 | try { 33 | gLawnApp = new LawnApp(); 34 | auto shouldChangeDir = 35 | (!Sexy::FileExists("properties/resources.xml") && Sexy::FileExists("../properties/resources.xml")) || 36 | (!Sexy::FileExists("main.pak") && Sexy::FileExists("../main.pak")); 37 | 38 | gLawnApp->mChangeDirTo = shouldChangeDir ? ".." : "."; 39 | gLawnApp->DoParseCmdLine(argc, argv); 40 | gLawnApp->Init(); 41 | gLawnApp->Start(); 42 | gLawnApp->Shutdown(); 43 | 44 | delete gLawnApp; 45 | } 46 | catch (std::runtime_error& aError) 47 | { 48 | LawnApp::HandleError(aError.what()); 49 | } 50 | 51 | return 0; 52 | }; 53 | -------------------------------------------------------------------------------- /src/framework/sound/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | target_sources(${PROJECT_NAME} PRIVATE 4 | "BassMusicInterface.cpp" 5 | "BassSoundInstance.cpp" 6 | "BassSoundManager.cpp" 7 | ) 8 | 9 | 10 | if (WIN32) 11 | set(BASS_SRC https://www.un4seen.com/files/bass24.zip) 12 | set(BASS_LIB c/x64/bass.lib) 13 | set(BASS_INCLUDE c) 14 | elseif (UNIX) 15 | if (APPLE) 16 | set(BASS_SRC https://www.un4seen.com/files/bass24-osx.zip) 17 | set(BASS_LIB libbass.dylib) 18 | else () 19 | set(BASS_SRC https://www.un4seen.com/files/bass24-linux.zip) 20 | set(BASS_LIB libs/x86_64/libbass.so) 21 | endif () 22 | set(BASS_INCLUDE "") 23 | endif () 24 | 25 | FetchContent_Declare( 26 | bass 27 | URL ${BASS_SRC} 28 | DOWNLOAD_EXTRACT_TIMESTAMP ${CMAKE_SOURCE_DIR}/external/bass/.timestamp 29 | ) 30 | 31 | FetchContent_GetProperties(bass) 32 | if (NOT bass_POPULATED) 33 | FetchContent_Populate(bass) 34 | file(COPY ${bass_SOURCE_DIR}/${BASS_LIB} DESTINATION ${CMAKE_BINARY_DIR}) 35 | endif () 36 | 37 | get_filename_component(bassfile ${BASS_LIB} NAME) 38 | 39 | add_library(bass STATIC IMPORTED GLOBAL) 40 | set_target_properties(bass PROPERTIES 41 | IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/${bassfile} 42 | ) 43 | 44 | target_link_libraries( 45 | ${PROJECT_NAME} 46 | PRIVATE 47 | bass 48 | ) 49 | 50 | target_include_directories( 51 | ${PROJECT_NAME} 52 | PRIVATE 53 | ${bass_SOURCE_DIR}/${BASS_INCLUDE} 54 | ) 55 | 56 | if (WIN32) 57 | configure_file("${bass_SOURCE_DIR}/x64/bass.dll" ${CMAKE_BINARY_DIR} COPYONLY) 58 | endif () -------------------------------------------------------------------------------- /src/framework/LawnProject.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // 中文(简体,中国) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) 19 | // LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED 20 | #pragma code_page(936) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include \r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "\r\n" 42 | "\0" 43 | END 44 | 45 | #endif // APSTUDIO_INVOKED 46 | 47 | 48 | ///////////////////////////////////////////////////////////////////////////// 49 | // 50 | // Cursor 51 | // 52 | 53 | IDC_CURSOR1 CURSOR "../Cursor13.cur" 54 | 55 | #endif // 中文(简体,中国) resources 56 | ///////////////////////////////////////////////////////////////////////////// 57 | 58 | 59 | 60 | #ifndef APSTUDIO_INVOKED 61 | ///////////////////////////////////////////////////////////////////////////// 62 | // 63 | // Generated from the TEXTINCLUDE 3 resource. 64 | // 65 | 66 | 67 | ///////////////////////////////////////////////////////////////////////////// 68 | #endif // not APSTUDIO_INVOKED 69 | -------------------------------------------------------------------------------- /src/framework/graphics/shaders/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SHADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}) 2 | set(SHADER_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/shaders) 3 | file(GLOB SHADERS 4 | ${SHADER_DIR}/*.vert 5 | ${SHADER_DIR}/*.frag 6 | ${SHADER_DIR}/*.comp 7 | ${SHADER_DIR}/*.geom 8 | ${SHADER_DIR}/*.tesc 9 | ${SHADER_DIR}/*.tese 10 | ${SHADER_DIR}/*.mesh 11 | ${SHADER_DIR}/*.task 12 | ${SHADER_DIR}/*.rgen 13 | ${SHADER_DIR}/*.rchit 14 | ${SHADER_DIR}/*.rmiss 15 | ) 16 | 17 | set(SHADER_DEPENDS "") 18 | 19 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 20 | set(GLSLC_FLAGS -g -O0) 21 | else () 22 | set(GLSLC_FLAGS -O) 23 | endif () 24 | 25 | file(MAKE_DIRECTORY ${SHADER_OUTPUT_DIR}) 26 | foreach (SHADER ${SHADERS}) 27 | get_filename_component(FILENAME ${SHADER} NAME) 28 | add_custom_command( 29 | OUTPUT ${SHADER_OUTPUT_DIR}/${FILENAME}.spv 30 | COMMAND ${Vulkan_GLSLC_EXECUTABLE} ${SHADER} -o ${SHADER_OUTPUT_DIR}/${FILENAME}.spv ${GLSLC_FLAGS} 31 | COMMENT "Compiling ${FILENAME}" 32 | DEPENDS ${SHADER}) 33 | add_custom_command( 34 | OUTPUT ${SHADER_OUTPUT_DIR}/${FILENAME}.spv.cpp 35 | COMMAND ${CMAKE_COMMAND} -Dbin="${SHADER_OUTPUT_DIR}/${FILENAME}.spv" -Doutput="${SHADER_OUTPUT_DIR}/${FILENAME}.spv.cpp" -P "${CMAKE_SOURCE_DIR}/cmake/embed_binary.cmake" 36 | COMMENT "Converting ${FILENAME} to C++" 37 | DEPENDS ${SHADER_OUTPUT_DIR}/${FILENAME}.spv) 38 | list(APPEND SHADER_DEPENDS ${SHADER_OUTPUT_DIR}/${FILENAME}.spv.cpp) 39 | endforeach () 40 | 41 | add_custom_target(shaders DEPENDS ${SHADER_DEPENDS}) 42 | add_library(shaders_lib STATIC ${SHADER_DEPENDS}) 43 | 44 | target_link_libraries(${PROJECT_NAME} PRIVATE shaders_lib) -------------------------------------------------------------------------------- /re-plants-vs-zombies.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": ".", 6 | } 7 | ], 8 | "settings": 9 | { 10 | "cmake": 11 | { 12 | "build_folder": "$folder/build", 13 | "generator": "Ninja", 14 | "command_line_overrides": 15 | { 16 | "CMAKE_TOOLCHAIN_FILE": "toolchain.cmake" 17 | }, 18 | }, 19 | }, 20 | "build_systems": 21 | [ 22 | { 23 | "config": "Release", 24 | "env": 25 | { 26 | }, 27 | "generator": "Ninja", 28 | "name": "Release", 29 | "target": "cmake_build", 30 | "variants": 31 | [ 32 | { 33 | "build_target": "LawnProject", 34 | "name": "LawnProject" 35 | }, 36 | { 37 | "artifact": "PlantsVsZombies", 38 | "build_target": "LawnProject", 39 | "name": "Run: LawnProject", 40 | "target": "cmake_run" 41 | }, 42 | { 43 | "artifact": "PlantsVsZombies", 44 | "build_target": "LawnProject", 45 | "debug": true, 46 | "name": "Run under GDB: LawnProject", 47 | "target": "cmake_run" 48 | }, 49 | { 50 | "build_target": "glfw-src", 51 | "name": "glfw-src" 52 | }, 53 | { 54 | "build_target": "libjpeg-src", 55 | "name": "libjpeg-src" 56 | }, 57 | { 58 | "build_target": "libpng-src", 59 | "name": "libpng-src" 60 | }, 61 | { 62 | "build_target": "rc", 63 | "name": "rc" 64 | }, 65 | { 66 | "build_target": "shader", 67 | "name": "shader" 68 | }, 69 | { 70 | "build_target": "zlib-src", 71 | "name": "zlib-src" 72 | }, 73 | { 74 | "name": "ctest", 75 | "target": "ctest_run" 76 | } 77 | ], 78 | "working_dir": "$folder/build" 79 | } 80 | ], 81 | } 82 | -------------------------------------------------------------------------------- /src/framework/misc/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef __POINT_H__ 2 | #define __POINT_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | template class TPoint { 8 | public: 9 | _T mX; 10 | _T mY; 11 | 12 | public: 13 | TPoint(_T theX, _T theY) : mX(theX), mY(theY) {} 14 | 15 | /* 16 | TPoint(const TPoint<_T>& theTPoint) : 17 | mX(theTPoint.mX), 18 | mY(theTPoint.mY) 19 | { 20 | } 21 | */ 22 | 23 | TPoint() : mX(0), mY(0) {} 24 | 25 | inline bool operator==(const TPoint &p) { return ((p.mX == mX) && (p.mY == mY)); } 26 | 27 | inline bool operator!=(const TPoint &p) { return ((p.mX != mX) || (p.mY != mY)); } 28 | 29 | TPoint operator+(const TPoint &p) const { return TPoint(mX + p.mX, mY + p.mY); } 30 | TPoint operator-(const TPoint &p) const { return TPoint(mX - p.mX, mY - p.mY); } 31 | TPoint operator*(const TPoint &p) const { return TPoint(mX * p.mX, mY * p.mY); } 32 | TPoint operator/(const TPoint &p) const { return TPoint(mX / p.mX, mY / p.mY); } 33 | 34 | TPoint &operator+=(const TPoint &p) { 35 | mX += p.mX; 36 | mY += p.mY; 37 | return *this; 38 | } 39 | 40 | TPoint &operator-=(const TPoint &p) { 41 | mX -= p.mX; 42 | mY -= p.mY; 43 | return *this; 44 | } 45 | 46 | TPoint &operator*=(const TPoint &p) { 47 | mX *= p.mX; 48 | mY *= p.mY; 49 | return *this; 50 | } 51 | 52 | TPoint &operator/=(const TPoint &p) { 53 | mX /= p.mX; 54 | mY /= p.mY; 55 | return *this; 56 | } 57 | 58 | TPoint operator*(_T s) const { return TPoint(mX * s, mY * s); } 59 | TPoint operator/(_T s) const { return TPoint(mX / s, mY / s); } 60 | }; 61 | 62 | using Point = TPoint; 63 | using FPoint = TPoint; 64 | }; // namespace Sexy 65 | 66 | #endif //__POINT_H__ 67 | -------------------------------------------------------------------------------- /src/framework/misc/Debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUG_INCLUDED__ 2 | #define __DEBUG_INCLUDED__ 3 | 4 | #include "framework/Common.h" 5 | #include 6 | 7 | extern bool gInAssert; 8 | 9 | #ifdef SEXY_TRACING_ENABLED 10 | void SexyTrace(const char *theStr); 11 | #define SEXY_TRACE(theStr) SexyTrace(theStr) 12 | #else 13 | #define SEXY_TRACE(theStr) 14 | #endif 15 | 16 | // extern void SexyTraceFmt(const SexyChar *fmt...); 17 | // extern void OutputDebug(const SexyChar *fmt...); 18 | 19 | #ifdef NDEBUG 20 | 21 | #define DBG_ASSERTE(exp) ((void)0) 22 | #define DBG_ASSERT(exp) ((void)0) 23 | 24 | #else 25 | 26 | #define DBG_ASSERTE(exp) \ 27 | { \ 28 | gInAssert = true; \ 29 | assert(exp); \ 30 | gInAssert = false; \ 31 | } 32 | #define DBG_ASSERT(exp) \ 33 | { \ 34 | gInAssert = true; \ 35 | assert(exp); \ 36 | gInAssert = false; \ 37 | } 38 | 39 | #endif // NDEBUG 40 | 41 | #endif //__DEBUG_INCLUDED__ 42 | -------------------------------------------------------------------------------- /src/lawn/system/ReanimationLawn.h: -------------------------------------------------------------------------------- 1 | #ifndef __REANIMATORCACHE_H__ 2 | #define __REANIMATORCACHE_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/graphics/Image.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace Sexy { 11 | class Graphics; 12 | }; 13 | 14 | using namespace Sexy; 15 | 16 | class LawnApp; 17 | 18 | class Reanimation; 19 | 20 | class ReanimatorCache { 21 | public: 22 | std::map> mImageVariationMap; 23 | std::unique_ptr mPlantImages[SeedType::NUM_SEED_TYPES] = {}; 24 | std::unique_ptr mLawnMowers[LawnMowerType::NUM_MOWER_TYPES] = {}; 25 | std::unique_ptr mZombieImages[ZombieType::NUM_CACHED_ZOMBIE_TYPES] = {}; 26 | 27 | public: 28 | // ReanimatorCache() { ReanimatorCacheInitialize(); } 29 | //~ReanimatorCache() { ReanimatorCacheDispose(); } 30 | 31 | void 32 | DrawCachedPlant(Graphics *g, float thePosX, float thePosY, SeedType theSeedType, DrawVariation theDrawVariation); 33 | void DrawCachedMower(Graphics *g, float thePosX, float thePosY, LawnMowerType theMowerType); 34 | void DrawCachedZombie(Graphics *g, float thePosX, float thePosY, ZombieType theZombieType); 35 | std::unique_ptr MakeBlankImage(int theWidth, int theHeight); 36 | std::unique_ptr MakeCachedPlantFrame(SeedType theSeedType, DrawVariation theDrawVariation); 37 | std::unique_ptr MakeCachedMowerFrame(LawnMowerType theMowerType); 38 | std::unique_ptr MakeCachedZombieFrame(ZombieType theZombieType); 39 | void GetPlantImageSize(SeedType theSeedType, int &theOffsetX, int &theOffsetY, int &theWidth, int &theHeight); 40 | void DrawReanimatorFrame( 41 | Graphics *g, float thePosX, float thePosY, ReanimationType theReanimationType, const char *theTrackName, 42 | DrawVariation theDrawVariation 43 | ); 44 | void UpdateReanimationForVariation(Reanimation *theReanim, DrawVariation theDrawVariation); 45 | }; 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /src/todlib/ReanimAtlas.h: -------------------------------------------------------------------------------- 1 | #ifndef __REANIMATLAS_H__ 2 | #define __REANIMATLAS_H__ 3 | 4 | #include "misc/Rect.h" 5 | #include 6 | using namespace Sexy; 7 | 8 | #define MAX_REANIM_IMAGES 64 9 | 10 | class ReanimatorDefinition; 11 | 12 | namespace Sexy { 13 | class Image; 14 | // class MemoryImage; 15 | }; // namespace Sexy 16 | 17 | class ReanimAtlasImage { 18 | public: 19 | int mX; 20 | int mY; 21 | int mWidth; 22 | int mHeight; 23 | Image *mOriginalImage; 24 | 25 | public: 26 | ReanimAtlasImage() : mX(0), mY(0), mWidth(0), mHeight(0), mOriginalImage(nullptr) {} 27 | }; 28 | 29 | bool sSortByNonIncreasingHeight(const ReanimAtlasImage &image1, const ReanimAtlasImage &image2); 30 | 31 | class ReanimAtlas { 32 | public: 33 | ReanimAtlasImage mImageArray[MAX_REANIM_IMAGES]; //+0x0 34 | int mImageCount; //+0x500 35 | std::unique_ptr mMemoryImage; //+0x504 36 | 37 | public: 38 | ReanimAtlas(); 39 | 40 | void ReanimAtlasCreate(const ReanimatorDefinition *theReanimDef); 41 | void ReanimAtlasDispose(); 42 | /*inline*/ void AddImage(Image *theImage); 43 | /*inline*/ int FindImage(const Image *theImage); 44 | bool ImageFits(int theImageCount, const Rect &rectTest, int theMaxWidth) const; 45 | bool ImageFindPlaceOnSide( 46 | ReanimAtlasImage *theAtlasImageToPlace, int theImageCount, int theMaxWidth, bool theToRight 47 | ) const; 48 | /*inline*/ bool ImageFindPlace(ReanimAtlasImage *theAtlasImageToPlace, int theImageCount, int theMaxWidth); 49 | /*inline*/ bool PlaceAtlasImage(ReanimAtlasImage *theAtlasImageToPlace, int theImageCount, int theMaxWidth); 50 | int PickAtlasWidth() const; 51 | void ArrangeImages(int &theAtlasWidth, int &theAtlasHeight); 52 | ReanimAtlasImage *GetEncodedReanimAtlas(Image *theImage); 53 | }; 54 | 55 | // MemoryImage* ReanimAtlasMakeBlankMemoryImage(int theWidth, int theHeight); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/framework/misc/Buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUFFER_H__ 2 | #define __BUFFER_H__ 3 | 4 | #include "framework/Common.h" 5 | #include 6 | 7 | namespace Sexy { 8 | using ByteVector = std::vector; 9 | 10 | class Buffer { 11 | public: 12 | ByteVector mData; 13 | int mDataBitSize; 14 | mutable int mReadBitPos; 15 | mutable int mWriteBitPos; 16 | 17 | public: 18 | Buffer(); 19 | virtual ~Buffer(); 20 | 21 | void SeekFront() const; 22 | void Clear(); 23 | 24 | void FromWebString(const std::string &theString); 25 | void WriteByte(uint8_t theByte); 26 | void WriteNumBits(int theNum, int theBits); 27 | static int GetBitsRequired(int theNum, bool isSigned); 28 | void WriteBoolean(bool theBool); 29 | void WriteShort(short theShort); 30 | void WriteLong(int32_t theLong); 31 | void WriteString(const std::string &theString); 32 | void WriteUTF8String(const std::wstring &theString); 33 | void WriteLine(const std::string &theString); 34 | void WriteBuffer(const ByteVector &theBuffer); 35 | void WriteBytes(const uint8_t *theByte, int theCount); 36 | void SetData(const ByteVector &theBuffer); 37 | void SetData(uint8_t *thePtr, int theCount); 38 | 39 | std::string ToWebString() const; 40 | std::wstring UTF8ToWideString() const; 41 | uint8_t ReadByte() const; 42 | int ReadNumBits(int theBits, bool isSigned) const; 43 | bool ReadBoolean() const; 44 | short ReadShort() const; 45 | int32_t ReadLong() const; 46 | std::string ReadString() const; 47 | std::wstring ReadUTF8String() const; 48 | std::string ReadLine() const; 49 | void ReadBytes(uint8_t *theData, int theLen) const; 50 | void ReadBuffer(ByteVector *theByteVector) const; 51 | 52 | const uint8_t *GetDataPtr() const; 53 | int GetDataLen() const; 54 | int GetDataLenBits() const; 55 | uint32_t GetCRC32(uint32_t theSeed = 0) const; 56 | 57 | bool AtEnd() const; 58 | bool PastEnd() const; 59 | }; 60 | } // namespace Sexy 61 | 62 | #endif //__BUFFER_H__ 63 | -------------------------------------------------------------------------------- /src/lawn/widget/AchievementsScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef __ACHIEVEMENTSSCREEN_H__ 2 | #define __ACHIEVEMENTSSCREEN_H__ 3 | // @Patoke: implement file 4 | 5 | #include "framework/widget/Widget.h" 6 | 7 | class LawnApp; 8 | 9 | using namespace Sexy; 10 | 11 | enum AchievementId { 12 | HomeSecurity, 13 | NovelPeasPrize, 14 | BetterOffDead, 15 | ChinaShop, 16 | Spudow, 17 | Explodonator, 18 | Morticulturalist, 19 | DontPea, 20 | RollSomeHeads, 21 | Grounded, 22 | Zombologist, 23 | PennyPincher, 24 | SunnyDays, 25 | PopcornParty, 26 | GoodMorning, 27 | NoFungusAmongUs, 28 | BeyondTheGrave, 29 | Immortal, 30 | ToweringWisdom, 31 | MustacheMode, 32 | MAX_ACHIEVEMENTS 33 | }; 34 | 35 | // todo @Patoke: add these 36 | class AchievementItem { 37 | public: 38 | std::string name; 39 | std::string description; 40 | }; 41 | 42 | extern AchievementItem gAchievementList[MAX_ACHIEVEMENTS]; 43 | 44 | class AchievementsWidget : public Widget { 45 | public: 46 | LawnApp *mApp; //+GOTY @Patoke: 0xA8 47 | int mScrollDirection; //+GOTY @Patoke: 0xAC 48 | Rect mMoreRockRect; //+GOTY @Patoke: 0xC0 49 | int mScrollValue; //+GOTY @Patoke: 0xB0 50 | int mScrollDecay; //+GOTY @Patoke: 0xB4 51 | int mDefaultScrollValue; //+GOTY @Patoke: 0xB8 52 | bool mDidPressMoreButton; //+GOTY @Patoke: 0xBC 53 | 54 | AchievementsWidget(LawnApp *theApp); 55 | ~AchievementsWidget() override; 56 | 57 | void Update() override; 58 | void Draw(Graphics *g) override; 59 | void KeyDown(KeyCode theKey) override; 60 | void MouseDown(int x, int y, int theClickCount) override; 61 | void MouseUp(int x, int y, int theClickCount) override; 62 | void MouseWheel(int theDelta) override; 63 | }; 64 | 65 | class ReportAchievement { 66 | public: 67 | static void GiveAchievement(LawnApp *theApp, int theAchievement, bool theForceGive); 68 | static void AchievementInitForPlayer(LawnApp *theApp); 69 | 70 | static bool mAchievementToShow; 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/todlib/EffectSystem.h: -------------------------------------------------------------------------------- 1 | #ifndef __EFFECTSYSTEM_H__ 2 | #define __EFFECTSYSTEM_H__ 3 | 4 | #include "framework/graphics/Graphics.h" 5 | #include 6 | using namespace Sexy; 7 | 8 | #define MAX_TRIANGLES 256 9 | 10 | class TodTriVertex { 11 | public: 12 | float x; 13 | float y; 14 | float u; 15 | float v; 16 | uint32_t color; 17 | }; 18 | 19 | class TodTriangleGroup { 20 | public: 21 | using VertexArray = std::array, MAX_TRIANGLES>; 22 | using VertexArrayPool = std::deque; 23 | 24 | static size_t gNumVertArraysInUse; 25 | static VertexArrayPool gVertArrays; 26 | 27 | VertexArray &mVertArray; 28 | Image *mImage = nullptr; 29 | // TriVertex mVertArray[MAX_TRIANGLES][3]; 30 | 31 | int mTriangleCount = 0; 32 | int mMaxTriangleCount = 0; 33 | int mDrawMode = Graphics::DRAWMODE_NORMAL; 34 | 35 | TodTriangleGroup(); 36 | ~TodTriangleGroup(); 37 | void DrawGroup(const Graphics *g); 38 | void AddTriangle( 39 | Graphics *g, Image *theImage, const SexyMatrix3 &theMatrix, const Rect &theClipRect, const Color &theColor, 40 | int theDrawMode, const Rect &theSrcRect 41 | ); 42 | }; 43 | 44 | extern bool gTodTriangleDrawAdditive; // 0x6A9EF5 45 | 46 | class Reanimation; 47 | class TodParticleHolder; 48 | class TrailHolder; 49 | class ReanimationHolder; 50 | class AttachmentHolder; 51 | 52 | class EffectSystem { 53 | public: 54 | TodParticleHolder *mParticleHolder; 55 | TrailHolder *mTrailHolder; 56 | ReanimationHolder *mReanimationHolder; 57 | AttachmentHolder *mAttachmentHolder; 58 | 59 | public: 60 | EffectSystem() 61 | : mParticleHolder(nullptr), mTrailHolder(nullptr), mReanimationHolder(nullptr), mAttachmentHolder(nullptr) {} 62 | 63 | ~EffectSystem() {} 64 | 65 | void EffectSystemInitialize(); 66 | void EffectSystemDispose(); 67 | void EffectSystemFreeAll() const; 68 | void ProcessDeleteQueue() const; 69 | void Update() const; 70 | }; 71 | 72 | extern EffectSystem *gEffectSystem; //[0x6A9EB8] 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/framework/widget/TextWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __TEXTWIDGET_H__ 2 | #define __TEXTWIDGET_H__ 3 | 4 | #include "ScrollListener.h" 5 | #include "Widget.h" 6 | 7 | namespace Sexy { 8 | class ScrollbarWidget; 9 | class _Font; 10 | 11 | using SexyStringVector = std::vector; 12 | using IntVector = std::vector; 13 | 14 | class TextWidget : public Widget, public ScrollListener { 15 | public: 16 | _Font *mFont; 17 | ScrollbarWidget *mScrollbar; 18 | 19 | SexyStringVector mLogicalLines; 20 | SexyStringVector mPhysicalLines; 21 | IntVector mLineMap; 22 | double mPosition; 23 | double mPageSize; 24 | bool mStickToBottom; 25 | int mHiliteArea[2][2]; 26 | int mMaxLines; 27 | 28 | public: 29 | TextWidget(); 30 | 31 | virtual SexyStringVector GetLines(); 32 | virtual void SetLines(SexyStringVector theNewLines); 33 | virtual void Clear(); 34 | virtual void DrawColorString(Graphics *g, const SexyString &theString, int x, int y, bool useColors); 35 | virtual void 36 | DrawColorStringHilited(Graphics *g, const SexyString &theString, int x, int y, int theStartPos, int theEndPos); 37 | virtual int GetStringIndex(const SexyString &theString, int thePixel); 38 | 39 | virtual int GetColorStringWidth(const SexyString &theString); 40 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 41 | virtual Color GetLastColor(const SexyString &theString); 42 | virtual void AddToPhysicalLines(int theIdx, const SexyString &theLine); 43 | 44 | virtual void AddLine(const SexyString &theString); 45 | virtual bool SelectionReversed(); 46 | virtual void GetSelectedIndices(int theLineIdx, int *theIndices); 47 | void Draw(Graphics *g) override; 48 | void ScrollPosition(int theId, double thePosition) override; 49 | virtual void GetTextIndexAt(int x, int y, int *thePosArray); 50 | virtual SexyString GetSelection(); 51 | 52 | void MouseDown(int x, int y, int theClickCount) override; 53 | void MouseDrag(int x, int y) override; 54 | 55 | void KeyDown(KeyCode theKey) override; 56 | }; 57 | } // namespace Sexy 58 | 59 | #endif //__TEXTWIDGET_H__ 60 | -------------------------------------------------------------------------------- /src/lawn/system/SaveGame.h: -------------------------------------------------------------------------------- 1 | #ifndef __SAVEGAMECONTEXT_H__ 2 | #define __SAVEGAMECONTEXT_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/misc/Buffer.h" 6 | #include "todlib/TodList.h" 7 | #include 8 | 9 | class Board; 10 | class Trail; 11 | enum GameMode; 12 | class Reanimation; 13 | class TodParticleSystem; 14 | class TodParticleEmitter; 15 | class ReanimatorDefinition; 16 | class TodParticleDefinition; 17 | class TrailDefinition; 18 | 19 | namespace Sexy { 20 | class Image; 21 | } 22 | 23 | using namespace Sexy; 24 | 25 | struct SaveFileHeader { 26 | unsigned int mMagicNumber; 27 | unsigned int mBuildVersion; 28 | unsigned int mBuildDate; 29 | }; 30 | 31 | class SaveGameContext { 32 | public: 33 | Buffer mBuffer; //+0x0 34 | bool mFailed; //+0x20 35 | bool mReading; //+0x21 36 | 37 | public: 38 | inline int ByteLeftToRead() { return (mBuffer.mDataBitSize - mBuffer.mReadBitPos + 7) / 8; } 39 | void SyncBytes(void *theDest, int theReadSize); 40 | void SyncInt(int &theInt); 41 | inline void SyncSizeT(size_t &theInt) { SyncBytes(&theInt, sizeof(size_t)); } 42 | ReanimationType SyncReanimationDef(ReanimatorDefinition *&theDefinition); 43 | void SyncParticleDef(TodParticleDefinition *&theDefinition); 44 | void SyncTrailDef(TrailDefinition *&theDefinition); 45 | void SyncImage(Image *&theImage); 46 | }; 47 | 48 | void SyncDataIDList(TodList *theDataIDList, SaveGameContext &theContext, TodAllocator *theAllocator); 49 | void SyncParticleEmitter( 50 | TodParticleSystem *theParticleSystem, TodParticleEmitter *theParticleEmitter, SaveGameContext &theContext 51 | ); 52 | void SyncParticleSystem(const Board *theBoard, TodParticleSystem *theParticleSystem, SaveGameContext &theContext); 53 | void SyncReanimation(const Board *theBoard, Reanimation *theReanimation, SaveGameContext &theContext); 54 | void SyncTrail(const Board *theBoard, Trail *theTrail, SaveGameContext &theContext); 55 | void SyncBoard(SaveGameContext &theContext, Board *theBoard); 56 | void FixBoardAfterLoad(Board *theBoard); 57 | bool LawnLoadGame(Board *theBoard, const std::string &theFilePath); 58 | bool LawnSaveGame(Board *theBoard, const std::string &theFilePath); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/framework/sound/BassSoundManager.h: -------------------------------------------------------------------------------- 1 | #ifndef __BASS_SOUND_MANAGER_H__ 2 | #define __BASS_SOUND_MANAGER_H__ 3 | 4 | #include "BassMusicInterface.h" 5 | #include "BassSoundInstance.h" 6 | #include "SoundManager.h" 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Sexy { 12 | class BassSoundManager : public Sexy::SoundManager { 13 | public: 14 | BassSoundManager(HWND theHWnd); 15 | static double PanDBToNorm(int dbpan); 16 | 17 | bool Initialized() override { return Sexy::BassMusicInterface::gBassLoaded; } 18 | 19 | bool LoadSound(unsigned int theSfxID, const std::string &theFilename) override; 20 | int LoadSound(const std::string &theFilename) override; 21 | void ReleaseSound(unsigned int theSfxID) override; 22 | 23 | void SetVolume(double theVolume) override; 24 | bool SetBaseVolume(unsigned int theSfxID, double theBaseVolume) override; 25 | bool SetBasePan(unsigned int theSfxID, int theBasePan) override; 26 | 27 | Sexy::SoundInstance *GetSoundInstance(unsigned int theSfxID) override; 28 | 29 | void ReleaseSounds() override; 30 | 31 | void ReleaseChannels() override {} 32 | 33 | double GetMasterVolume() override { return 1.0; } 34 | 35 | void SetMasterVolume(double) override {} 36 | 37 | void Flush() override {} 38 | 39 | // virtual void SetCooperativeWindow(HWND theHWnd) {} 40 | void StopAllSounds() override {} 41 | 42 | int GetFreeSoundId() override; 43 | int GetNumSounds() override; 44 | 45 | private: 46 | std::array>, MAX_CHANNELS> mPlayingSounds; 47 | std::array mSourceFileNames; 48 | std::array, MAX_SOURCE_SOUNDS> mSourceSounds; 49 | 50 | bool LoadCompatibleSound(unsigned int theSfxID, const std::string &theFilename); 51 | bool LoadAUSound(unsigned int theSfxID, const std::string &theFilename); 52 | inline bool Exists(unsigned int theSfxID) const; 53 | static void 54 | SetBaseVolumeAndPan(HSAMPLE theSample, std::optional theBaseVolume, std::optional theBasePan); 55 | int FindFreeChannel(); 56 | void ReleaseFreeChannels(); 57 | }; 58 | } // namespace Sexy 59 | 60 | #endif // __BASS_SOUND_MANAGER_H__ 61 | -------------------------------------------------------------------------------- /src/framework/graphics/WindowInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_INTERFACE_H 2 | #define WINDOW_INTERFACE_H 3 | 4 | #include "framework/graphics/Image.h" 5 | using namespace Sexy; 6 | 7 | enum PointerType { 8 | CURSOR_POINTER, 9 | CURSOR_HAND, 10 | CURSOR_DRAGGING, 11 | CURSOR_TEXT, 12 | CURSOR_CIRCLE_SLASH, 13 | CURSOR_SIZEALL, 14 | CURSOR_SIZENESW, 15 | CURSOR_SIZENS, 16 | CURSOR_SIZENWSE, 17 | CURSOR_SIZEWE, 18 | CURSOR_WAIT, 19 | CURSOR_NONE, 20 | CURSOR_DEFAULT, 21 | CURSOR_CUSTOM, 22 | NUM_POINTER_TYPES, 23 | }; 24 | 25 | /* 26 | * This looks cursed but what it actually is is an attempt to avoid using 27 | * runtime polymorphism to implement a simple interface. This is mostly a 28 | * programming jihadism thing because such a powerful hammer shouldn't need 29 | * to be used on such a small nail, but it's also a little bit faster. Anyway 30 | * this is an example of 'F-bounded polymorphism' implemented using the 31 | * adorably named curiously recurring template pattern. (CRTP) 32 | */ 33 | 34 | template class WindowInterface { 35 | public: 36 | Image *GetScreenImage() { return static_cast(this)->GetScreenImage(); } 37 | void ShowWindow() { static_cast(this)->ShowWindow(); } 38 | void PollEvents() { static_cast(this)->PollEvents(); } 39 | void RehupFocus() { static_cast(this)->RehupFocus(); } 40 | bool ShouldClose() { return static_cast(this)->ShouldClose(); } 41 | void ReleaseMouseCapture() { static_cast(this)->ReleaseMouseCapture(); } 42 | void Draw() { static_cast(this)->Draw(); } 43 | void EnforceCursor() { static_cast(this)->EnforceCursor(); } 44 | 45 | int 46 | CreateCursor(int xHotSpot, int yHotSpot, int nWidth, int nHeight, const void *pvANDPlane, const void *pvXORPlane) { 47 | return static_cast(this)->CreateCursor(xHotSpot, yHotSpot, nWidth, nHeight, pvANDPlane, pvXORPlane); 48 | } 49 | 50 | void UpdateWindowOptions(const int width, const int height, const bool fullscreen) { 51 | static_cast(this)->UpdateWindowOptions(width, height, fullscreen); 52 | } 53 | 54 | int GetRefreshRate() { return static_cast(this)->GetRefreshRate(); } 55 | }; 56 | 57 | #endif // WINDOW_INTERFACE_H 58 | -------------------------------------------------------------------------------- /src/lawn/widget/NewOptionsDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __NEWOPTIONSDIALOG_H__ 2 | #define __NEWOPTIONSDIALOG_H__ 3 | 4 | #include "framework/widget/CheckboxListener.h" 5 | #include "framework/widget/Dialog.h" 6 | #include "framework/widget/SliderListener.h" 7 | 8 | class LawnApp; 9 | class LawnStoneButton; 10 | class NewLawnButton; 11 | 12 | namespace Sexy { 13 | class Slider; 14 | class Checkbox; 15 | }; // namespace Sexy 16 | 17 | class NewOptionsDialog : public Sexy::Dialog, public Sexy::SliderListener, public Sexy::CheckboxListener { 18 | protected: 19 | enum { 20 | NewOptionsDialog_Almanac, 21 | NewOptionsDialog_MainMenu, 22 | NewOptionsDialog_Restart, 23 | NewOptionsDialog_Update, 24 | NewOptionsDialog_MusicVolume, 25 | NewOptionsDialog_SoundVolume, 26 | NewOptionsDialog_Fullscreen, 27 | NewOptionsDialog_HardwareAcceleration, 28 | }; 29 | 30 | public: 31 | LawnApp *mApp; //+0x158 32 | Sexy::Slider *mMusicVolumeSlider; //+0x15C 33 | Sexy::Slider *mSfxVolumeSlider; //+0x160 34 | Sexy::Checkbox *mFullscreenCheckbox; //+0x164 35 | Sexy::Checkbox *mHardwareAccelerationCheckbox; //+0x168 36 | LawnStoneButton *mAlmanacButton; //+0x16C 37 | LawnStoneButton *mBackToMainButton; //+0x170 38 | LawnStoneButton *mRestartButton; //+0x174 39 | NewLawnButton *mBackToGameButton; //+0x178 40 | bool mFromGameSelector; //+0x17C 41 | 42 | public: 43 | NewOptionsDialog(LawnApp *theApp, bool theFromGameSelector); 44 | ~NewOptionsDialog() override; 45 | 46 | int GetPreferredHeight(int theWidth) override; 47 | void AddedToManager(Sexy::WidgetManager *theWidgetManager) override; 48 | void RemovedFromManager(Sexy::WidgetManager *theWidgetManager) override; 49 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 50 | void Draw(Sexy::Graphics *g) override; 51 | void SliderVal(int theId, double theVal) override; 52 | void CheckboxChecked(int theId, bool checked) override; 53 | void ButtonPress(int theId) override; 54 | void ButtonDepress(int theId) override; 55 | void KeyDown(Sexy::KeyCode theKey) override; 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/framework/widget/ScrollbuttonWidget.cpp: -------------------------------------------------------------------------------- 1 | #include "ScrollbuttonWidget.h" 2 | #include "ButtonListener.h" 3 | #include "graphics/Graphics.h" 4 | 5 | using namespace Sexy; 6 | 7 | ScrollbuttonWidget::ScrollbuttonWidget(int theId, ButtonListener *theButtonListener, int theType) 8 | : ButtonWidget(theId, theButtonListener) { 9 | mHorizontal = false; 10 | mType = theType; 11 | } 12 | 13 | ScrollbuttonWidget::~ScrollbuttonWidget() {} 14 | 15 | void ScrollbuttonWidget::Draw(Graphics *g) { 16 | int anArrowOffset = 0; 17 | 18 | g->SetColor(Color(212, 212, 212)); 19 | g->FillRect(0, 0, mWidth, mHeight); 20 | 21 | if (mIsDown && mIsOver && !mDisabled) { 22 | anArrowOffset = 1; 23 | g->SetColor(Color(132, 132, 132)); 24 | g->DrawRect(0, 0, mWidth - 1, mHeight - 1); 25 | } else { 26 | g->SetColor(Color(255, 255, 255)); 27 | g->FillRect(1, 1, mWidth - 2, 1); 28 | g->FillRect(1, 1, 1, mHeight - 2); 29 | 30 | g->SetColor(Color::Black); 31 | g->FillRect(0, mHeight - 1, mWidth, 1); 32 | g->FillRect(mWidth - 1, 0, 1, mHeight); 33 | 34 | g->SetColor(Color(132, 132, 132)); 35 | g->FillRect(1, mHeight - 2, mWidth - 2, 1); 36 | g->FillRect(mWidth - 2, 1, 1, mHeight - 2); 37 | } 38 | 39 | if (!mDisabled) g->SetColor(Color::Black); 40 | else g->SetColor(Color(132, 132, 132)); 41 | 42 | if (mHorizontal || (mType == 3 || mType == 4)) { 43 | for (int i = 0; i < 4; i++) { 44 | if (mId == 0 || mType == 3) 45 | g->FillRect(i + (mWidth - 4) / 2 + anArrowOffset, mHeight / 2 - i - 1 + anArrowOffset, 1, 1 + i * 2); 46 | else 47 | g->FillRect( 48 | (3 - i) + (mWidth - 4) / 2 + anArrowOffset, mHeight / 2 - i - 1 + anArrowOffset, 1, 1 + i * 2 49 | ); 50 | } 51 | } else { 52 | for (int i = 0; i < 4; i++) { 53 | if (mId == 0 || mType == 1) 54 | g->FillRect(mWidth / 2 - i - 1 + anArrowOffset, i + (mHeight - 4) / 2 + anArrowOffset, 1 + i * 2, 1); 55 | else 56 | g->FillRect( 57 | mWidth / 2 - i - 1 + anArrowOffset, (3 - i) + (mHeight - 4) / 2 + anArrowOffset, 1 + i * 2, 1 58 | ); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/framework/widget/ButtonWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __BUTTONWIDGET_H__ 2 | #define __BUTTONWIDGET_H__ 3 | 4 | #include "Widget.h" 5 | 6 | namespace Sexy { 7 | class Image; 8 | class ButtonListener; 9 | 10 | class ButtonWidget : public Widget { 11 | public: 12 | enum { BUTTON_LABEL_LEFT = -1, BUTTON_LABEL_CENTER, BUTTON_LABEL_RIGHT }; 13 | 14 | enum { 15 | COLOR_LABEL, 16 | COLOR_LABEL_HILITE, 17 | COLOR_DARK_OUTLINE, 18 | COLOR_LIGHT_OUTLINE, 19 | COLOR_MEDIUM_OUTLINE, 20 | COLOR_BKG, 21 | NUM_COLORS 22 | }; 23 | 24 | int mId; 25 | SexyString mLabel; 26 | int mLabelJustify; 27 | _Font *mFont; 28 | Image *mButtonImage; 29 | Image *mOverImage; 30 | Image *mDownImage; 31 | Image *mDisabledImage; 32 | Rect mNormalRect; 33 | Rect mOverRect; 34 | Rect mDownRect; 35 | Rect mDisabledRect; 36 | 37 | bool mInverted; 38 | bool mBtnNoDraw; 39 | bool mFrameNoDraw; 40 | ButtonListener *mButtonListener; 41 | 42 | double mOverAlpha; 43 | double mOverAlphaSpeed; 44 | double mOverAlphaFadeInSpeed; 45 | 46 | static bool HaveButtonImage(const Image *theImage, const Rect &theRect); 47 | virtual void DrawButtonImage(Graphics *g, Image *theImage, const Rect &theRect, int x, int y); 48 | 49 | public: 50 | ButtonWidget(const int theId, ButtonListener *theButtonListener); 51 | ~ButtonWidget() override; 52 | 53 | virtual void SetFont(_Font *theFont); 54 | virtual bool IsButtonDown(); 55 | void Draw(Graphics *g) override; 56 | void SetDisabled(bool isDisabled) override; 57 | void MouseEnter() override; 58 | void MouseLeave() override; 59 | void MouseMove(int theX, int theY) override; 60 | void MouseDown(int theX, int theY, int theClickCount) override { Widget::MouseDown(theX, theY, theClickCount); } 61 | void MouseDown(int theX, int theY, int theBtnNum, int theClickCount) override; 62 | void MouseUp(int theX, int theY) override { Widget::MouseUp(theX, theY); } 63 | void MouseUp(int theX, int theY, int theClickCount) override { Widget::MouseUp(theX, theY, theClickCount); } 64 | void MouseUp(int theX, int theY, int theBtnNum, int theClickCount) override; 65 | void Update() override; 66 | }; 67 | } // namespace Sexy 68 | 69 | #endif //__BUTTONWIDGET_H__ 70 | -------------------------------------------------------------------------------- /src/framework/widget/Checkbox.cpp: -------------------------------------------------------------------------------- 1 | #include "Checkbox.h" 2 | #include "CheckboxListener.h" 3 | #include "graphics/Graphics.h" 4 | 5 | using namespace Sexy; 6 | 7 | Checkbox::Checkbox(Image *theUncheckedImage, Image *theCheckedImage, int theId, CheckboxListener *theCheckboxListener) 8 | : mListener(theCheckboxListener), mId(theId), mChecked(false), mUncheckedImage(theUncheckedImage), 9 | mCheckedImage(theCheckedImage), mOutlineColor(Color::White), mBkgColor(Color(80, 80, 80)), 10 | mCheckColor(Color(255, 255, 0)) { 11 | mDoFinger = true; 12 | } 13 | 14 | void Checkbox::SetChecked(bool checked, bool tellListener) { 15 | mChecked = checked; 16 | if (tellListener && mListener) mListener->CheckboxChecked(mId, mChecked); 17 | MarkDirty(); 18 | } 19 | 20 | bool Checkbox::IsChecked() { return mChecked; } 21 | 22 | void Checkbox::Draw(Graphics *g) { 23 | Widget::Draw(g); 24 | 25 | /*if (mChecked) 26 | g->DrawImage(mApp->mImages[IMAGE_CHECKBOX], 0, 0, Rect(0, 0, 31, 32)); 27 | else 28 | g->DrawImage(mApp->mImages[IMAGE_CHECKBOX], 0, 0, Rect(31, 0, 31, 32));*/ 29 | 30 | if ((mCheckedRect.mWidth == 0) && (mCheckedImage != nullptr) && (mUncheckedImage != nullptr)) { 31 | if (mChecked) g->DrawImage(mCheckedImage, 0, 0); 32 | else g->DrawImage(mUncheckedImage, 0, 0); 33 | } else if ((mCheckedRect.mWidth != 0) && (mUncheckedImage != nullptr)) { 34 | if (mChecked) g->DrawImage(mUncheckedImage, 0, 0, mCheckedRect); 35 | else g->DrawImage(mUncheckedImage, 0, 0, mUncheckedRect); 36 | } else if ((mUncheckedImage == nullptr) && (mCheckedImage == nullptr)) { 37 | // No image, default draw method 38 | g->SetColor(mOutlineColor); 39 | g->FillRect(0, 0, mWidth, mHeight); 40 | g->SetColor(mBkgColor); 41 | g->FillRect(1, 1, mWidth - 2, mHeight - 2); 42 | 43 | if (mChecked) { 44 | g->SetColor(mCheckColor); 45 | g->DrawLine(1, 1, mWidth - 2, mHeight - 2); 46 | g->DrawLine(mWidth - 1, 1, 1, mHeight - 2); 47 | } 48 | } 49 | } 50 | 51 | void Checkbox::MouseDown(int x, int y, int theBtnNum, int theClickCount) { 52 | Widget::MouseDown(x, y, theBtnNum, theClickCount); 53 | 54 | mChecked = !mChecked; 55 | if (mListener) mListener->CheckboxChecked(mId, mChecked); 56 | MarkDirty(); 57 | } 58 | -------------------------------------------------------------------------------- /src/framework/sound/BassMusicInterface.h: -------------------------------------------------------------------------------- 1 | #ifndef __BASSMUSICINTERFACE_H__ 2 | #define __BASSMUSICINTERFACE_H__ 3 | 4 | #include "MusicInterface.h" 5 | #include "bass.h" 6 | #include 7 | 8 | namespace Sexy { 9 | #ifndef _WIN32 10 | #define HWND void * 11 | #endif 12 | 13 | class SexyAppBase; 14 | 15 | class BassMusicInfo { 16 | public: 17 | HMUSIC mHMusic; 18 | HSTREAM mHStream; 19 | double mVolume; 20 | double mVolumeAdd; 21 | double mVolumeCap; 22 | bool mStopOnFade; 23 | 24 | public: 25 | BassMusicInfo(); 26 | 27 | DWORD GetHandle() { return mHMusic ? mHMusic : mHStream; } 28 | }; 29 | 30 | using BassMusicMap = std::map; 31 | 32 | class BassMusicInterface : public MusicInterface { 33 | public: 34 | static bool gBassLoaded; 35 | static void InitBass(HWND theHWnd); 36 | 37 | BassMusicMap mMusicMap; 38 | int mMaxMusicVolume; 39 | int mMusicLoadFlags; 40 | 41 | public: 42 | BassMusicInterface(HWND theHWnd); 43 | ~BassMusicInterface() override; 44 | 45 | bool LoadMusic(int theSongId, const std::string &theFileName) override; 46 | void PlayMusic(int theSongId, int theOffset = 0, bool noLoop = false) override; 47 | void StopMusic(int theSongId) override; 48 | void StopAllMusic() override; 49 | void UnloadMusic(int theSongId) override; 50 | void UnloadAllMusic() override; 51 | void PauseAllMusic() override; 52 | void ResumeAllMusic() override; 53 | void PauseMusic(int theSongId) override; 54 | void ResumeMusic(int theSongId) override; 55 | void FadeIn(int theSongId, int theOffset = -1, double theSpeed = 0.002, bool noLoop = false) override; 56 | void FadeOut(int theSongId, bool stopSong = true, double theSpeed = 0.004) override; 57 | void FadeOutAll(bool stopSong = true, double theSpeed = 0.004) override; 58 | void SetSongVolume(int theSongId, double theVolume) override; 59 | void SetSongMaxVolume(int theSongId, double theMaxVolume) override; 60 | bool IsPlaying(int theSongId) override; 61 | 62 | void SetVolume(double theVolume) override; 63 | void SetMusicAmplify(int theSongId, double theAmp) override; // default is 0.50 64 | void Update() override; 65 | 66 | // functions for dealing with MODs 67 | int GetMusicOrder(int theSongId); 68 | }; 69 | } // namespace Sexy 70 | 71 | #endif //__BASSMUSICINTERFACE_H__ 72 | -------------------------------------------------------------------------------- /src/framework/SexyApp.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEXYAPP_H__ 2 | #define __SEXYAPP_H__ 3 | 4 | #include "SexyAppBase.h" 5 | 6 | namespace Sexy { 7 | class InternetManager; 8 | class BetaSupport; 9 | 10 | class SexyApp : public SexyAppBase { 11 | public: 12 | InternetManager *mInternetManager; 13 | BetaSupport *mBetaSupport; 14 | 15 | std::string mBetaSupportSiteOverride; 16 | std::string mBetaSupportProdNameOverride; 17 | std::string mReferId; 18 | std::string mVariation; 19 | uint32_t mDownloadId; 20 | std::string mRegSource; 21 | uint32_t mLastVerCheckQueryTime; 22 | bool mSkipAd; 23 | bool mDontUpdate; 24 | 25 | int mBuildNum; 26 | std::string mBuildDate; 27 | 28 | std::string mUserName; 29 | std::string mRegUserName; 30 | std::string mRegCode; 31 | bool mIsRegistered; 32 | bool mBuildUnlocked; 33 | 34 | int mTimesPlayed; 35 | int mTimesExecuted; 36 | bool mTimedOut; 37 | 38 | #ifdef ZYLOM 39 | uint mZylomGameId; 40 | #endif 41 | 42 | public: 43 | void UpdateFrames() override; 44 | 45 | void WriteToRegistry() override; 46 | void ReadFromRegistry() override; 47 | 48 | // virtual bool CheckSignature(const Buffer& theBuffer, const std::string& theFileName); 49 | 50 | virtual bool ShouldCheckForUpdate(); 51 | virtual void UpdateCheckQueried(); 52 | 53 | void URLOpenSucceeded(const std::string &theURL) override; 54 | 55 | public: 56 | SexyApp(); 57 | ~SexyApp() override; 58 | 59 | // bool Validate(const std::string& theUserName, const std::string& theRegCode); 60 | 61 | // virtual bool OpenRegisterPage(DefinesMap theDefinesMap); 62 | virtual bool OpenRegisterPage(); 63 | 64 | void PreDisplayHook() override; 65 | void InitPropertiesHook() override; 66 | void Init() override; 67 | void PreTerminate() override; 68 | 69 | virtual bool OpenHTMLTemplate(const std::string &theTemplateFile, const DefinesMap &theDefinesMap); 70 | virtual void OpenUpdateURL(); 71 | 72 | void HandleCmdLineParam(const std::string &theParamName, const std::string &theParamValue) override; 73 | virtual std::string GetGameSEHInfo(); 74 | void GetSEHWebParams(DefinesMap *theDefinesMap) override; 75 | 76 | #ifdef ZYLOM 77 | bool ZylomUpdateCheckNeeded(); 78 | void ZylomShowAd(); 79 | #endif 80 | }; 81 | 82 | extern SexyApp *gSexyApp; 83 | }; // namespace Sexy 84 | 85 | #endif //__SEXYAPP_H__ 86 | -------------------------------------------------------------------------------- /src/compiler/quick_sort.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | // From https://tristanbrindle.com/posts/a-more-useful-compile-time-quicksort 6 | namespace compiler { 7 | namespace _sort { 8 | template constexpr RAIt _next(RAIt it, typename std::iterator_traits::difference_type n = 1) { 9 | return it + n; 10 | } 11 | 12 | template constexpr auto _distance(RAIt first, RAIt last) { return last - first; } 13 | 14 | template constexpr void _iter_swap(ForwardIt1 a, ForwardIt2 b) { 15 | auto temp = std::move(*a); 16 | *a = std::move(*b); 17 | *b = std::move(temp); 18 | } 19 | 20 | template 21 | constexpr InputIt _find_if_not(InputIt first, InputIt last, UnaryPredicate q) { 22 | for (; first != last; ++first) { 23 | if (!q(*first)) { 24 | return first; 25 | } 26 | } 27 | return last; 28 | } 29 | 30 | template 31 | constexpr ForwardIt _partition(ForwardIt first, ForwardIt last, UnaryPredicate p) { 32 | first = _find_if_not(first, last, p); 33 | if (first == last) return first; 34 | 35 | for (ForwardIt i = _next(first); i != last; ++i) { 36 | if (p(*i)) { 37 | _iter_swap(i, first); 38 | ++first; 39 | } 40 | } 41 | return first; 42 | } 43 | 44 | template > 45 | constexpr void quick_sort(RAIt first, RAIt last, Compare cmp = Compare{}) { 46 | auto const N = _distance(first, last); 47 | if (N <= 1) return; 48 | auto const pivot = *_next(first, N / 2); 49 | auto const middle1 = _partition(first, last, [=](auto const &elem) { return cmp(elem, pivot); }); 50 | auto const middle2 = _partition(middle1, last, [=](auto const &elem) { return !cmp(pivot, elem); }); 51 | quick_sort(first, middle1, cmp); 52 | quick_sort(middle2, last, cmp); 53 | } 54 | } // namespace _sort 55 | 56 | template > constexpr auto sort(Range &&range, Compare cmp = Compare{}) { 57 | auto first = std::begin(range); 58 | auto last = std::end(range); 59 | _sort::quick_sort(first, last, cmp); 60 | } 61 | } // namespace compiler 62 | -------------------------------------------------------------------------------- /src/lawn/widget/TitleScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef __TITLESCREEN_H__ 2 | #define __TITLESCREEN_H__ 3 | 4 | #include "framework/widget/ButtonListener.h" 5 | #include "framework/widget/Widget.h" 6 | 7 | using namespace Sexy; 8 | 9 | enum TitleState { 10 | TITLESTATE_WAITING_FOR_FIRST_DRAW, 11 | TITLESTATE_POPCAP_LOGO, 12 | TITLESTATE_PARTNER_LOGO, 13 | TITLESTATE_SCREEN 14 | }; 15 | 16 | namespace Sexy { 17 | class HyperlinkWidget; 18 | } 19 | 20 | class LawnApp; 21 | 22 | class TitleScreen : public Sexy::Widget, public Sexy::ButtonListener { 23 | public: 24 | enum { TitleScreen_Start, TitleScreen_Register }; 25 | 26 | public: 27 | HyperlinkWidget *mStartButton; //+0x8C 28 | float mCurBarWidth; //+0x90 29 | float mTotalBarWidth; //+0x94 30 | float mBarVel; //+0x98 31 | float mBarStartProgress; //+0x9C 32 | bool mRegisterClicked; //+0xA0 33 | bool mLoadingThreadComplete; //+0xA1 34 | int mTitleAge; //+0xA4 35 | KeyCode mQuickLoadKey; //+0xA8 36 | bool mNeedRegister; //+0xAC 37 | bool mNeedShowRegisterBox; //+0xAD 38 | bool mDrawnYet; //+0xAE 39 | bool mNeedToInit; //+0xAF 40 | float mPrevLoadingPercent; //+0xB0 41 | TitleState mTitleState; //+0xB4 42 | int mTitleStateCounter; //+0xB8 43 | int mTitleStateDuration; //+0xBC 44 | bool mDisplayPartnerLogo; //+0xC0 45 | bool mLoaderScreenIsLoaded; //+0xC1 46 | LawnApp *mApp; //+0xC4 47 | 48 | public: 49 | TitleScreen(LawnApp *theApp); 50 | ~TitleScreen() override; 51 | 52 | void Update() override; 53 | void Draw(Graphics *g) override; 54 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 55 | void AddedToManager(WidgetManager *theWidgetManager) override; 56 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 57 | void ButtonPress(int theId) override; 58 | void ButtonDepress(int theId) override; 59 | 60 | void ButtonDownTick(int) override {} 61 | 62 | void ButtonMouseEnter(int) override {} 63 | 64 | void ButtonMouseLeave(int) override {} 65 | 66 | void ButtonMouseMove(int, int, int) override {} 67 | 68 | void MouseDown(int x, int y, int theClickCount) override; 69 | void KeyDown(KeyCode theKey) override; 70 | void SetRegistered(); 71 | void DrawToPreload(Graphics *g); 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/framework/misc/ModVal.h: -------------------------------------------------------------------------------- 1 | #ifndef __MODVAL_H__ 2 | #define __MODVAL_H__ 3 | 4 | #include 5 | 6 | /* 7 | This module allows for dynamic modification of integer and floating-point 8 | constants at run-time. 9 | 10 | Place the M() around values you want to allow to be changed at run-time. 11 | When you want to modify a value, simply change the value in the source 12 | code file and call ReparseModValues() within your program to re-read the 13 | source files, checking for changes in constants. Your program will need 14 | to contain some trigger such as a key combination to trigger the 15 | ReparseModValues() call. 16 | 17 | Example: 18 | x = x + M(2.1); 19 | 20 | Caveats: 21 | This module determines which files to parse through (during 22 | ReparseModValues()) at run-time, so if a M() macro has not yet been 23 | executed within a particular source file, its value will not be 24 | updated. 25 | 26 | Performance: 27 | There a small setup cost the first time each M() value is accessed 28 | after program startup and reparsing, but after that there is just the 29 | tiny overhead of a function call and a few vector dereferences. 30 | 31 | */ 32 | 33 | namespace Sexy { 34 | 35 | #if defined(SEXY_DISABLE_MODVAL) || defined(RELEASEFINAL) 36 | #define M(val) (val) 37 | #define M1(val) (val) 38 | #define M2(val) (val) 39 | #define M3(val) (val) 40 | #define M4(val) (val) 41 | #define M5(val) (val) 42 | #define M6(val) (val) 43 | #define M7(val) (val) 44 | #define M8(val) (val) 45 | #define M9(val) (val) 46 | #else 47 | #define MODVAL_STR_COUNTER2(x, y, z) x #y "," #z 48 | #define MODVAL_STR_COUNTER1(x, y, z) MODVAL_STR_COUNTER2(x, y, z) 49 | #define MODVAL_STR_COUNTER(x) MODVAL_STR_COUNTER1(x, __COUNTER__, __LINE__) 50 | #define M(val) ModVal(0, MODVAL_STR_COUNTER("SEXY_SEXYMODVAL" __FILE__), (val)) 51 | #define M1(val) M(val) 52 | #define M2(val) M(val) 53 | #define M3(val) M(val) 54 | #define M4(val) M(val) 55 | #define M5(val) M(val) 56 | #define M6(val) M(val) 57 | #define M7(val) M(val) 58 | #define M8(val) M(val) 59 | #define M9(val) M(val) 60 | #endif 61 | 62 | int ModVal(const char *theFileName, int theInt); 63 | double ModVal(const char *theFileName, double theDouble); 64 | float ModVal(const char *theFileName, float theFloat); 65 | const char *ModVal(const char *theFileName, const char *theStr); 66 | bool ReparseModValues(); 67 | void AddModValEnum(const std::string &theEnumName, int theVal); 68 | 69 | } // namespace Sexy 70 | 71 | #endif //__MODVAL_H__ 72 | -------------------------------------------------------------------------------- /src/lawn/LawnCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef __LAWN_COMMON_H__ 2 | #define __LAWN_COMMON_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/graphics/Graphics.h" 6 | #include "framework/widget/EditWidget.h" 7 | 8 | using namespace Sexy; 9 | // using namespace std; 10 | 11 | class Board; 12 | class LawnStoneButton; 13 | class NewLawnButton; 14 | 15 | namespace Sexy { 16 | class Dialog; 17 | class Checkbox; 18 | class DialogButton; 19 | class CheckboxListener; 20 | } // namespace Sexy 21 | 22 | class LawnEditWidget : public EditWidget { 23 | public: 24 | Dialog *mDialog; 25 | bool mAutoCapFirstLetter; 26 | 27 | public: 28 | LawnEditWidget(int theId, EditListener *theListener, Dialog *theDialog); 29 | ~LawnEditWidget() override; 30 | 31 | void KeyDown(KeyCode theKey) override; 32 | void KeyChar(char theChar) override; 33 | }; 34 | 35 | // ==================================================================================================== 36 | // ★ 常用逻辑判断 37 | // ==================================================================================================== 38 | /*inline*/ bool ModInRange(int theNumber, int theMod, int theRange = 0); 39 | /*inline*/ bool GridInRange(int x1, int y1, int x2, int y2, int theRangeX = 1, int theRangeY = 1); 40 | 41 | // ==================================================================================================== 42 | // ★ 动画、特效与绘制相关 43 | // ==================================================================================================== 44 | /*inline*/ void TileImageHorizontally(Graphics *g, Image *theImage, int theX, int theY, int theWidth); 45 | /*inline*/ void TileImageVertically(Graphics *g, Image *theImage, int theX, int theY, int theHeight); 46 | 47 | // ==================================================================================================== 48 | // ★ 控件 49 | // ==================================================================================================== 50 | Checkbox *MakeNewCheckbox(int theId, CheckboxListener *theListener, bool theDefault); 51 | LawnEditWidget *CreateEditWidget(int theId, EditListener *theListener, Dialog *theDialog); 52 | void DrawEditBox(Graphics *g, const EditWidget *theWidget); 53 | 54 | // ==================================================================================================== 55 | // ★ 其他 56 | // ==================================================================================================== 57 | std::string GetSavedGameName(GameMode theGameMode, int theProfileId); 58 | int GetCurrentDaysSince2000(); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/framework/graphics/shaders/water.comp: -------------------------------------------------------------------------------- 1 | #version 450 2 | 3 | layout(set = 0, binding = 0) buffer readonly CausticGrayscaleImage { 4 | uint aBits[]; 5 | }; 6 | 7 | layout(set = 0, binding = 1) buffer writeonly StagingBuffer { 8 | uint data[]; 9 | }; 10 | 11 | layout(set = 0, binding = 2) buffer PoolCounter { 12 | uint mPoolCounter; 13 | }; 14 | 15 | layout(set = 0, binding = 3) uniform readonly ScaleBlock { 16 | float SCALE; 17 | }; 18 | 19 | // local size expected to be (128 * SCALE, 64 * SCALE, 1) 20 | 21 | uint BilinearLookupFixedPoint(int u, int v) { 22 | const uint timeU = u & 0xFFFF0000; 23 | const uint timeV = v & 0xFFFF0000; 24 | const uint factorU1 = uint(int(u - timeU) & 0x0000FFFE) + 1; 25 | const uint factorV1 = uint(int(v - timeV) & 0x0000FFFE) + 1; 26 | const uint factorU0 = 65536 - factorU1; 27 | const uint factorV0 = 65536 - factorV1; 28 | const uint indexU0 = (timeU >> 16) % 256; 29 | const uint indexU1 = ((timeU >> 16) + 1) % 256; 30 | const uint indexV0 = (timeV >> 16) % 256; 31 | const uint indexV1 = ((timeV >> 16) + 1) % 256; 32 | 33 | return ((((factorU0 * factorV1) >> 16) * (aBits[indexV1 * 256 + indexU0] & 0xFF000000 >> 24)) >> 16) + 34 | ((((factorU1 * factorV1) >> 16) * (aBits[indexV1 * 256 + indexU1] & 0xFF000000 >> 24)) >> 16) + 35 | ((((factorU0 * factorV0) >> 16) * (aBits[indexV0 * 256 + indexU0] & 0xFF000000 >> 24)) >> 16) + 36 | ((((factorU1 * factorV0) >> 16) * (aBits[indexV0 * 256 + indexU1] & 0xFF000000 >> 24)) >> 16); 37 | } 38 | 39 | void main() { 40 | int x = int(gl_GlobalInvocationID.x); 41 | int y = int(gl_GlobalInvocationID.y); 42 | uint idx = uint(x + y * gl_NumWorkGroups.x); 43 | 44 | const float timeU = float(x << 17) / SCALE; 45 | const float timeV0 = float(y << 17) / SCALE; 46 | const float timeV1 = float(256 << 17) - timeV0; 47 | 48 | const float timePool0 = int(mPoolCounter) << 16; 49 | const float timePool1 = ((int(mPoolCounter) & 65535) + 1) << 16; 50 | 51 | const uint a1 = BilinearLookupFixedPoint( 52 | int(timeU - timePool1 / 6), 53 | int(timeV1 + timePool0 / 8)); 54 | const uint a0 = BilinearLookupFixedPoint( 55 | int(timeU + timePool0 / 10), 56 | int(timeV0)); 57 | const uint a = (a0 + a1) / 2; 58 | 59 | uint alpha = 0; 60 | if (a >= 160U) { 61 | alpha = 255 - 2 * (a - 160U); 62 | } else if (a >= 128U) { 63 | alpha = 5 * (a - 128U); 64 | } 65 | 66 | const int v = int(alpha / 3); 67 | data[idx] = v | (v << 8) | (v << 16) | (v << 24); 68 | } 69 | -------------------------------------------------------------------------------- /src/GameConstants.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ConstEnums.h" 4 | constexpr const double PI = 3.141592653589793; 5 | 6 | // ============================================================ 7 | // ■ 常数 8 | // ============================================================ 9 | constexpr int BOARD_WIDTH = 800; 10 | constexpr int BOARD_HEIGHT = 600; 11 | constexpr int WIDE_BOARD_WIDTH = 800; 12 | constexpr int BOARD_OFFSET = 220; 13 | constexpr int BOARD_EDGE = -100; 14 | constexpr int BOARD_IMAGE_WIDTH_OFFSET = 1180; 15 | constexpr int BOARD_ICE_START = 800; 16 | constexpr int LAWN_XMIN = 40; 17 | constexpr int LAWN_YMIN = 80; 18 | constexpr int HIGH_GROUND_HEIGHT = 30; 19 | 20 | constexpr int SEEDBANK_MAX = 10; 21 | constexpr int SEED_BANK_OFFSET_X = 0; 22 | constexpr int SEED_BANK_OFFSET_X_END = 10; 23 | constexpr int SEED_CHOOSER_OFFSET_Y = 516; 24 | constexpr int SEED_PACKET_WIDTH = 50; 25 | constexpr int SEED_PACKET_HEIGHT = 70; 26 | constexpr int IMITATER_DIALOG_WIDTH = 500; 27 | constexpr int IMITATER_DIALOG_HEIGHT = 600; 28 | 29 | // ============================================================ 30 | // ■ 关卡相关 31 | // ============================================================ 32 | constexpr int ADVENTURE_AREAS = 5; 33 | constexpr int LEVELS_PER_AREA = 10; 34 | constexpr int NUM_LEVELS = ADVENTURE_AREAS * LEVELS_PER_AREA; 35 | constexpr int FINAL_LEVEL = NUM_LEVELS; 36 | constexpr int FLAG_RAISE_TIME = 100; 37 | constexpr int LAST_STAND_FLAGS = 5; 38 | constexpr int ZOMBIE_COUNTDOWN_FIRST_WAVE = 1800; 39 | constexpr int ZOMBIE_COUNTDOWN = 2500; 40 | constexpr int ZOMBIE_COUNTDOWN_RANGE = 600; 41 | constexpr int ZOMBIE_COUNTDOWN_BEFORE_FLAG = 4500; 42 | constexpr int ZOMBIE_COUNTDOWN_BEFORE_REPICK = 5499; 43 | constexpr int ZOMBIE_COUNTDOWN_MIN = 400; 44 | constexpr int FOG_BLOW_RETURN_TIME = 2000; 45 | constexpr int SUN_COUNTDOWN = 425; 46 | constexpr int SUN_COUNTDOWN_RANGE = 275; 47 | constexpr int SUN_COUNTDOWN_MAX = 950; 48 | constexpr int SURVIVAL_NORMAL_FLAGS = 5; 49 | constexpr int SURVIVAL_HARD_FLAGS = 10; 50 | 51 | // ============================================================ 52 | // ■ 商店相关 53 | // ============================================================ 54 | constexpr int STORESCREEN_ITEMOFFSET_1_X = 422; 55 | constexpr int STORESCREEN_ITEMOFFSET_1_Y = 206; 56 | constexpr int STORESCREEN_ITEMOFFSET_2_X = 372; 57 | constexpr int STORESCREEN_ITEMOFFSET_2_Y = 310; 58 | constexpr int STORESCREEN_ITEMSIZE = 74; 59 | constexpr int STORESCREEN_COINBANK_X = 650; 60 | constexpr int STORESCREEN_COINBANK_Y = 559; 61 | constexpr int STORESCREEN_PAGESTRING_X = 470; 62 | constexpr int STORESCREEN_PAGESTRING_Y = 500; 63 | -------------------------------------------------------------------------------- /src/framework/misc/XMLParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __XMLPARSER_H__ 2 | #define __XMLPARSER_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | #include "PerfTimer.h" 7 | 8 | struct PFILE; 9 | 10 | namespace Sexy { 11 | class XMLParam { 12 | public: 13 | std::string mKey; 14 | std::string mValue; 15 | }; 16 | 17 | using XMLParamMap = std::map; 18 | using XMLParamMapIteratorList = std::list; 19 | 20 | using XMLParserBuffer = std::vector; 21 | 22 | class XMLElement { 23 | public: 24 | enum { TYPE_NONE, TYPE_START, TYPE_END, TYPE_ELEMENT, TYPE_INSTRUCTION, TYPE_COMMENT }; 25 | 26 | public: 27 | int mType; 28 | SexyString mSection; 29 | SexyString mValue; 30 | SexyString mInstruction; 31 | XMLParamMap mAttributes; 32 | XMLParamMapIteratorList mAttributeIteratorList; // stores attribute iterators in their original order 33 | }; 34 | 35 | class XMLParser { 36 | protected: 37 | std::string mFileName; 38 | SexyString mErrorText; 39 | int mLineNum; 40 | PFILE *mFile; 41 | bool mHasFailed; 42 | bool mAllowComments; 43 | XMLParserBuffer mBufferedText; 44 | SexyString mSection; 45 | bool (XMLParser::*mGetCharFunc)(wchar_t *theChar, bool *error); 46 | bool mForcedEncodingType; 47 | bool mFirstChar; 48 | bool mByteSwap; 49 | 50 | protected: 51 | void Fail(const SexyString &theErrorText); 52 | void Init(); 53 | 54 | bool AddAttribute(XMLElement *theElement, const SexyString &aAttributeKey, const SexyString &aAttributeValue); 55 | 56 | bool GetAsciiChar(wchar_t *theChar, bool *error); 57 | bool GetUTF8Char(wchar_t *theChar, bool *error); 58 | bool GetUTF16Char(wchar_t *theChar, bool *error); 59 | bool GetUTF16LEChar(wchar_t *theChar, bool *error); 60 | bool GetUTF16BEChar(wchar_t *theChar, bool *error); 61 | 62 | public: 63 | enum XMLEncodingType { ASCII, UTF_8, UTF_16, UTF_16_LE, UTF_16_BE }; 64 | 65 | public: 66 | XMLParser(); 67 | virtual ~XMLParser(); 68 | 69 | void SetEncodingType(XMLEncodingType theEncoding); 70 | bool OpenFile(const std::string &theFilename); 71 | void SetStringSource(const std::wstring &theString); 72 | void SetStringSource(const std::string &theString); 73 | bool NextElement(XMLElement *theElement); 74 | SexyString GetErrorText(); 75 | int GetCurrentLineNum() const; 76 | std::string GetFileName(); 77 | 78 | inline void AllowComments(bool doAllow) { mAllowComments = doAllow; } 79 | 80 | bool HasFailed() const; 81 | bool EndOfFile(); 82 | }; 83 | }; // namespace Sexy 84 | 85 | #endif //__XMLPARSER_H__ 86 | -------------------------------------------------------------------------------- /src/lawn/Coin.h: -------------------------------------------------------------------------------- 1 | #ifndef __COIN_H__ 2 | #define __COIN_H__ 3 | 4 | #include "GameObject.h" 5 | #include "system/PlayerInfo.h" 6 | 7 | class HitResult; 8 | 9 | namespace Sexy { 10 | class Graphics; 11 | } 12 | 13 | using namespace Sexy; 14 | 15 | class Coin : public GameObject { 16 | public: 17 | float mPosX; //+0x24 18 | float mPosY; //+0x28 19 | float mVelX; //+0x2C 20 | float mVelY; //+0x30 21 | float mScale; //+0x34 22 | bool mDead; //+0x38 23 | int mFadeCount; //+0x3C 24 | float mCollectX; //+0x40 25 | float mCollectY; //+0x44 26 | int mGroundY; //+0x48 27 | int mCoinAge; //+0x4C 28 | bool mIsBeingCollected; //+0x50 29 | int mDisappearCounter; //+0x54 30 | CoinType mType; //+0x58 31 | CoinMotion mCoinMotion; //+0x5C 32 | AttachmentID mAttachmentID; //+0x60 33 | float mCollectionDistance; //+0x64 34 | SeedType mUsableSeedType; //+0x68 35 | PottedPlant mPottedPlantSpec; //+0x70 36 | bool mNeedsBouncyArrow; //+0xC8 37 | bool mHasBouncyArrow; //+0xC9 38 | bool mHitGround; //+0xCA 39 | int mTimesDropped; //+0xCC 40 | 41 | public: 42 | Coin(); 43 | ~Coin(); 44 | 45 | void CoinInitialize(int theX, int theY, CoinType theCoinType, CoinMotion theCoinMotion); 46 | void MouseDown(int x, int y, int theClickCount); 47 | bool MouseHitTest(int theX, int theY, HitResult *theHitResult); 48 | void Die(); 49 | void StartFade(); 50 | void Update(); 51 | void Draw(Graphics *g); 52 | void Collect(); 53 | /*inline*/ int GetSunValue() const; 54 | static /*inline*/ int GetCoinValue(CoinType theCoinType); 55 | void UpdateFade(); 56 | void UpdateFall(); 57 | void ScoreCoin(); 58 | void UpdateCollected(); 59 | Color GetColor(); 60 | /*inline*/ bool IsMoney() const; 61 | /*inline*/ bool IsSun(); 62 | float GetSunScale() const; 63 | static inline bool IsOnGround() { return false; } 64 | SeedType GetFinalSeedPacketType(); 65 | bool IsLevelAward(); 66 | bool CoinGetsBouncyArrow(); 67 | void FanOutCoins(CoinType theCoinType, int theNumCoins); 68 | int GetDisappearTime(); 69 | void DroppedUsableSeed(); 70 | void PlayCollectSound(); 71 | void TryAutoCollectAfterLevelAward(); 72 | bool IsPresentWithAdvice() const; 73 | void PlayLaunchSound(); 74 | void PlayGroundSound(); 75 | 76 | static /*inline*/ bool IsMoney(CoinType theType); 77 | }; 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/framework/misc/RegistryEmulator.h: -------------------------------------------------------------------------------- 1 | #ifndef REGISTRY_EMULATOR_H 2 | #define REGISTRY_EMULATOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /**********************************************************************************************/ 10 | /* Adapted from github.com/Alexpux/mingw-w64/blob/master/mingw-w64-tools/widl/include/winnt.h */ 11 | /**********************************************************************************************/ 12 | 13 | enum class SexyReg : uint32_t { 14 | NONE = 0, /* no type */ 15 | SZ = 1, /* string type (ASCII) */ 16 | EXPAND_SZ = 2, /* string, includes %ENVVAR% (expanded by caller) (ASCII) */ 17 | BINARY = 3, /* binary format, callerspecific */ 18 | 19 | /* YES, REG_DWORD == REG_DWORD_LITTLE_ENDIAN */ 20 | DWORD = 4, /* DWORD in little endian format */ 21 | DWORD_LITTLE_ENDIAN = 4, /* DWORD in little endian format */ 22 | DWORD_BIG_ENDIAN = 5, /* DWORD in big endian format */ 23 | LINK = 6, /* symbolic link (UNICODE) */ 24 | MULTI_SZ = 7, /* multiple strings, delimited by \0, terminated by \0\0 (ASCII) */ 25 | RESOURCE_LIST = 8, /* resource list? huh? */ 26 | FULL_RESOURCE_DESCRIPTOR = 9, /* full resource descriptor? huh? */ 27 | RESOURCE_REQUIREMENTS_LIST = 10, 28 | QWORD = 11, /* QWORD in little endian format */ 29 | QWORD_LITTLE_ENDIAN = 11 /* QWORD in little endian format */ 30 | }; 31 | 32 | /***********************************************************************************************/ 33 | 34 | class RegistryEmulator { 35 | public: 36 | struct RegistryHeader { 37 | uint64_t mMagic; 38 | uint64_t mNumEntries; 39 | }; 40 | 41 | struct RegistryEntry { 42 | uint64_t mValueNameLength; 43 | uint64_t mValueType; 44 | uint64_t mValueLength; 45 | }; 46 | 47 | explicit RegistryEmulator(const std::string &theFileName); 48 | 49 | RegistryEmulator() : RegistryEmulator("registry.dat") {} 50 | 51 | ~RegistryEmulator(); 52 | bool Read(const std::string &theValueName, SexyReg &theType, std::vector &theValue, uint32_t &theLength); 53 | void Write(const std::string &theValueName, SexyReg theType, const uint8_t *theValue, uint32_t theLength); 54 | bool Erase(const std::string &theValueName); 55 | size_t Flush() const; 56 | 57 | static constexpr uint64_t RegistryMagic() { return 0x8101454D; } 58 | 59 | private: 60 | const std::string mREG_FILENAME; 61 | std::map>> mRegMap; 62 | }; 63 | 64 | #endif // REGISTRY_EMULATOR_H 65 | -------------------------------------------------------------------------------- /src/framework/widget/ScrollbarWidget.h: -------------------------------------------------------------------------------- 1 | // ScrollbarWidget.h: interface for the ScrollbarWidget class. 2 | // 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #ifndef __SCROLLBARWIDGET_H__ 6 | #define __SCROLLBARWIDGET_H__ 7 | 8 | #include "ButtonListener.h" 9 | #include "Widget.h" 10 | 11 | namespace Sexy { 12 | class ScrollListener; 13 | class ScrollbuttonWidget; 14 | 15 | class ScrollbarWidget : public Widget, public ButtonListener { 16 | public: 17 | enum { UPDATE_MODE_IDLE = 0, UPDATE_MODE_PGUP, UPDATE_MODE_PGDN }; 18 | 19 | public: 20 | ScrollbuttonWidget *mUpButton; 21 | ScrollbuttonWidget *mDownButton; 22 | 23 | bool mInvisIfNoScroll; 24 | 25 | public: 26 | int mId; 27 | 28 | double mValue; 29 | double mMaxValue; 30 | double mPageSize; 31 | bool mHorizontal; 32 | 33 | bool mPressedOnThumb; 34 | int mMouseDownThumbPos; 35 | int mMouseDownX; 36 | int mMouseDownY; 37 | 38 | int mUpdateMode; 39 | int mUpdateAcc; 40 | int mButtonAcc; 41 | int mLastMouseX; 42 | int mLastMouseY; 43 | ScrollListener *mScrollListener; 44 | 45 | public: 46 | ScrollbarWidget(int theId, ScrollListener *theScrollListener); 47 | ~ScrollbarWidget() override; 48 | 49 | virtual void SetInvisIfNoScroll(bool invisIfNoScroll); 50 | virtual void SetMaxValue(double theNewMaxValue); 51 | virtual void SetPageSize(double theNewPageSize); 52 | virtual void SetValue(double theNewValue); 53 | virtual void SetHorizontal(bool isHorizontal); 54 | 55 | virtual void ResizeScrollbar(int theX, int theY, int theWidth, int theHeight); 56 | virtual bool AtBottom(); 57 | virtual void GoToBottom(); 58 | virtual void DrawThumb(Graphics *g, int theX, int theY, int theWidth, int theHeight); 59 | virtual int GetTrackSize(); 60 | virtual int GetThumbSize(); 61 | virtual int GetThumbPosition(); 62 | void Draw(Graphics *g) override; 63 | virtual void ClampValue(); 64 | virtual void SetThumbPosition(int thePosition); 65 | void ButtonPress(int theId) override; 66 | void ButtonDepress(int theId) override; 67 | void ButtonDownTick(int theId) override; 68 | void Update() override; 69 | virtual int ThumbCompare(int x, int y); 70 | void MouseDown(int x, int y, int theClickCount) override { Widget::MouseDown(x, y, theClickCount); } 71 | void MouseDown(int x, int y, int theBtnNum, int theClickCount) override; 72 | void MouseUp(int x, int y) override { Widget::MouseUp(x, y); } 73 | void MouseUp(int x, int y, int theBtnNum, int theClickCount) override; 74 | void MouseDrag(int x, int y) override; 75 | }; 76 | } // namespace Sexy 77 | 78 | #endif // __SCROLLBARWIDGET_H__ 79 | -------------------------------------------------------------------------------- /src/framework/sound/BassSoundInstance.cpp: -------------------------------------------------------------------------------- 1 | #include "BassSoundInstance.h" 2 | #include "BassSoundManager.h" 3 | #include 4 | 5 | namespace Sexy { 6 | BassSoundInstance::BassSoundInstance(HSAMPLE theSourceSound) : mSample(theSourceSound) { 7 | mChannel = BASS_SampleGetChannel(mSample, 0); 8 | } 9 | 10 | BassSoundInstance::~BassSoundInstance() { BASS_ChannelStop(mChannel); } 11 | 12 | void BassSoundInstance::RehupVolume() const { BASS_ChannelSetAttribute(mChannel, BASS_ATTRIB_VOL, mVolume); } 13 | 14 | void BassSoundInstance::RehupPan() const { 15 | BASS_ChannelSetAttribute(mChannel, BASS_ATTRIB_PAN, BassSoundManager::PanDBToNorm(mPan)); 16 | } 17 | 18 | void BassSoundInstance::Release() { 19 | Stop(); 20 | mReleased = true; 21 | } 22 | 23 | void BassSoundInstance::SetVolume(double theVolume) // 0 = max 24 | { 25 | mVolume = theVolume; 26 | RehupVolume(); 27 | } 28 | 29 | void BassSoundInstance::SetPan(int thePosition) //-db to =db = left to right 30 | { 31 | mPan = thePosition; 32 | RehupPan(); 33 | } 34 | 35 | bool BassSoundInstance::Play(bool looping, bool autoRelease) { 36 | Stop(); 37 | 38 | mHasPlayed = true; 39 | mAutoRelease = autoRelease; 40 | 41 | BASS_ChannelFlags(mChannel, looping ? BASS_SAMPLE_LOOP : 0, BASS_SAMPLE_LOOP); 42 | 43 | if (BASS_ErrorGetCode() != BASS_OK) return false; 44 | 45 | return BASS_ChannelStart(mChannel); 46 | } 47 | 48 | void BassSoundInstance::Stop() { 49 | BASS_ChannelPause(mChannel); 50 | mAutoRelease = false; 51 | } 52 | 53 | const double ONE_SEMITONE = pow(2.0, 1.0 / 12.0); 54 | 55 | void BassSoundInstance::AdjustPitch(double theNumSteps) { 56 | const double aFrequencyMult = pow(ONE_SEMITONE, theNumSteps); 57 | const double aNewFrequency = mDefaultFrequency * aFrequencyMult; 58 | 59 | /* 60 | if (aNewFrequency < DSBFREQUENCY_MIN) 61 | aNewFrequency = DSBFREQUENCY_MIN; 62 | if (aNewFrequency > DSBFREQUENCY_MAX) 63 | aNewFrequency = DSBFREQUENCY_MAX;*/ 64 | 65 | BASS_ChannelSetAttribute(mChannel, BASS_ATTRIB_FREQ, aNewFrequency); 66 | } 67 | 68 | int BassSoundInstance::GetSoundPosition() { return BASS_ChannelGetPosition(mChannel, BASS_POS_BYTE); } 69 | 70 | void BassSoundInstance::SetSoundPosition(int thePosition) { 71 | BASS_ChannelSetPosition(mChannel, BASS_POS_BYTE, thePosition); 72 | } 73 | 74 | bool BassSoundInstance::IsPlaying() { return (BASS_ChannelIsActive(mChannel) == BASS_ACTIVE_PLAYING); } 75 | 76 | bool BassSoundInstance::IsReleased() { 77 | if ((!mReleased) && (mAutoRelease) && (mHasPlayed) && (!IsPlaying())) Release(); 78 | 79 | return mReleased; 80 | } 81 | 82 | double BassSoundInstance::GetVolume() { return mVolume; } 83 | } // namespace Sexy 84 | -------------------------------------------------------------------------------- /src/framework/.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /src/framework/misc/SexyMatrix.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEXYMATRIX_H__ 2 | #define __SEXYMATRIX_H__ 3 | 4 | #include "SexyVector.h" 5 | #include 6 | #include 7 | 8 | namespace Sexy { 9 | /////////////////////////////////////////////////////////////////////////////// 10 | /////////////////////////////////////////////////////////////////////////////// 11 | class SexyMatrix3 { 12 | public: 13 | union { 14 | float m[3][3]; 15 | 16 | struct { 17 | float m00, m01, m02; 18 | float m10, m11, m12; 19 | float m20, m21, m22; 20 | }; 21 | 22 | glm::mat3 mat; 23 | }; 24 | 25 | public: 26 | SexyMatrix3(); 27 | 28 | SexyMatrix3(const glm::mat3 &m) : mat(m) {} 29 | 30 | void ZeroMatrix(); 31 | void LoadIdentity(); 32 | 33 | SexyVector2 operator*(const SexyVector2 &theVec) const; 34 | SexyVector3 operator*(const SexyVector3 &theVec) const; 35 | SexyMatrix3 operator*(const SexyMatrix3 &theMat) const; 36 | const SexyMatrix3 &operator*=(const SexyMatrix3 &theMat); 37 | }; 38 | 39 | /////////////////////////////////////////////////////////////////////////////// 40 | /////////////////////////////////////////////////////////////////////////////// 41 | class SexyTransform2D : public SexyMatrix3 { 42 | public: 43 | SexyTransform2D(); 44 | SexyTransform2D(bool loadIdentity); 45 | SexyTransform2D(const SexyMatrix3 &theMatrix); 46 | 47 | const SexyTransform2D &operator=(const SexyMatrix3 &theMat); 48 | 49 | void Translate(float tx, float ty); 50 | 51 | // Rotate has been replaced by RotateRad. 52 | // NOTE: If you had Rotate(angle) you should now use RotateRad(-angle). 53 | // This is to make positive rotations go counter-clockwise when using screen coordinates. 54 | void RotateRad(float rot); 55 | void RotateDeg(float rot); 56 | void Scale(float sx, float sy); 57 | }; 58 | 59 | /////////////////////////////////////////////////////////////////////////////// 60 | /////////////////////////////////////////////////////////////////////////////// 61 | class Transform { 62 | protected: 63 | mutable SexyTransform2D mMatrix; 64 | mutable bool mNeedCalcMatrix; 65 | void MakeComplex(); 66 | void CalcMatrix() const; 67 | 68 | public: 69 | bool mComplex, mHaveRot, mHaveScale; 70 | float mTransX1, mTransY1, mTransX2, mTransY2; 71 | float mScaleX, mScaleY; 72 | float mRot; 73 | 74 | public: 75 | Transform(); 76 | 77 | void Reset(); 78 | 79 | void Translate(float tx, float ty); 80 | void RotateRad(float rot); 81 | void RotateDeg(float rot); 82 | void Scale(float sx, float sy); 83 | 84 | const SexyTransform2D &GetMatrix() const; 85 | }; 86 | } // namespace Sexy 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/lawn/SeedPacket.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEEDPACKET_H__ 2 | #define __SEEDPACKET_H__ 3 | 4 | #include "GameConstants.h" 5 | #include "GameObject.h" 6 | 7 | constexpr const int SLOT_MACHINE_TIME = 400; 8 | constexpr const int CONVEYOR_SPEED = 4; 9 | 10 | class HitResult; 11 | 12 | class SeedPacket : public GameObject { 13 | public: 14 | int mRefreshCounter; //+0x24 15 | int mRefreshTime; //+0x28 16 | int mIndex; //+0x2C 17 | int mOffsetX; //+0x30 18 | SeedType mPacketType; //+0x34 19 | SeedType mImitaterType; //+0x38 20 | int mSlotMachineCountDown; //+0x3C 21 | SeedType mSlotMachiningNextSeed; //+0x40 22 | float mSlotMachiningPosition; //+0x44 23 | bool mActive; //+0x48 24 | bool mRefreshing; //+0x49 25 | int mTimesUsed; //+0x4C 26 | 27 | public: 28 | SeedPacket(); 29 | 30 | void Update(); 31 | void Draw(Graphics *g) const; 32 | void MouseDown(int x, int y, int theClickCount); 33 | bool MouseHitTest(int theX, int theY, HitResult *theHitResult); 34 | void Deactivate(); 35 | void Activate(); 36 | /*inline*/ void SetActivate(bool theActivate); 37 | void PickNextSlotMachineSeed(); 38 | void WasPlanted(); 39 | /*inline*/ void SlotMachineStart(); 40 | void FlashIfReady(); 41 | bool CanPickUp(); 42 | void SetPacketType(SeedType theSeedType, SeedType theImitaterType = SeedType::SEED_NONE); 43 | }; 44 | 45 | class SeedBank : public GameObject { 46 | public: 47 | int mNumPackets; //+0x24 48 | SeedPacket mSeedPackets[SEEDBANK_MAX]; //+0x28 49 | int mCutSceneDarken; //+0x348 50 | int mConveyorBeltCounter; //+0x34C 51 | 52 | public: 53 | SeedBank(); 54 | 55 | void Draw(Graphics *g); 56 | bool MouseHitTest(int x, int y, HitResult *theHitResult); 57 | 58 | inline void Move(int x, int y) { 59 | mX = x; 60 | mY = y; 61 | } 62 | 63 | bool ContainsPoint(int theX, int theY); 64 | void AddSeed(SeedType theSeedType, bool thePlaceOnLeft = false); 65 | void RemoveSeed(int theIndex); 66 | int GetNumSeedsOnConveyorBelt(); 67 | /*inline*/ int CountOfTypeOnConveyorBelt(SeedType theSeedType); 68 | void UpdateConveyorBelt(); 69 | void UpdateWidth(); 70 | void RefreshAllPackets(); 71 | }; 72 | 73 | void SeedPacketDrawSeed( 74 | Graphics *g, float x, float y, SeedType theSeedType, SeedType theImitaterType, float theOffsetX, float theOffsetY, 75 | float theScale 76 | ); 77 | void DrawSeedPacket( 78 | Graphics *g, float x, float y, SeedType theSeedType, SeedType theImitaterType, float thePercentDark, 79 | int theGrayness, bool theDrawCost, bool theUseCurrentCost 80 | ); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /tools/unpak.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define FILEFLAGS_END 0x80 7 | 8 | typedef struct PakDef { 9 | uint8_t aFlags; 10 | uint8_t aNameWidth; 11 | char *aName; 12 | int aSrcSize; 13 | uint64_t aFileTime; 14 | size_t offset; 15 | } PakDef; 16 | 17 | void PakDefPrint(PakDef *def) { 18 | printf( 19 | "Flags: %d, Name Width: %d, Name: %s, File Size: %d, Filetime: %ld, Offset: %zu\n", def->aFlags, def->aNameWidth, 20 | def->aName, def->aSrcSize, def->aFileTime, def->offset 21 | ); 22 | } 23 | 24 | int main() { 25 | FILE *fp = fopen("main.pak", "rb"); 26 | 27 | if (fp == NULL) { 28 | printf("Failed to open file main.pak\n"); 29 | return 1; 30 | } 31 | 32 | fseek(fp, 0, SEEK_END); 33 | size_t size = ftell(fp); 34 | rewind(fp); 35 | 36 | char *b_ptr = malloc(size); 37 | fread(b_ptr, 1, size, fp); 38 | fclose(fp); 39 | 40 | for (int i = 0; i < size; i++) 41 | b_ptr[i] = (b_ptr[i]) ^ 0xF7; // 'Decrypt' 42 | 43 | char *ptr = b_ptr + 8; 44 | int aPos = 0; 45 | 46 | PakDef defs[4096]; 47 | int idx = 0; 48 | for (;; ++idx) { 49 | if (ptr > (b_ptr + size)) break; 50 | PakDef *def = &defs[idx]; 51 | def->aFlags = *(uint8_t *)ptr; 52 | ptr += 1; 53 | if (def->aFlags & FILEFLAGS_END) break; 54 | 55 | def->aNameWidth = *(uint8_t *)ptr; 56 | ptr += 1; 57 | def->aName = malloc(def->aNameWidth + 1); 58 | memcpy(def->aName, ptr, def->aNameWidth); 59 | def->aName[def->aNameWidth] = 0; 60 | 61 | int nameIdx = 0; 62 | while (def->aName[nameIdx]) { 63 | if (def->aName[nameIdx] == '\\') def->aName[nameIdx] = '/'; 64 | nameIdx++; 65 | } 66 | ptr += def->aNameWidth; 67 | 68 | def->aSrcSize = *(int *)ptr; 69 | ptr += sizeof(int); 70 | def->aFileTime = *(uint64_t *)ptr; 71 | ptr += sizeof(uint64_t); 72 | 73 | def->offset = aPos; 74 | aPos += def->aSrcSize; 75 | } 76 | 77 | size_t offset = ptr - b_ptr; 78 | 79 | printf("%ld\n", offset); 80 | 81 | for (int i = 0; i < idx; ++i) { 82 | FILE *fd = fopen(defs[i].aName, "wb+"); 83 | 84 | if (!fd) { 85 | printf("Failed on %s\n", defs[i].aName); 86 | break; 87 | } 88 | 89 | defs[i].offset += offset; 90 | fwrite(b_ptr + defs[i].offset, 1, defs[i].aSrcSize, fd); 91 | fclose(fd); 92 | PakDefPrint(&defs[i]); 93 | } 94 | 95 | for (int i = 0; i < idx; ++i) { 96 | free(defs[i].aName); 97 | } 98 | free(b_ptr); 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/framework/graphics/Color.cpp: -------------------------------------------------------------------------------- 1 | #include "Color.h" 2 | 3 | using namespace Sexy; 4 | 5 | Color Color::Black(0, 0, 0); 6 | Color Color::White(255, 255, 255); 7 | 8 | Color::Color() : mRed(0), mGreen(0), mBlue(0), mAlpha(255) {} 9 | 10 | Color::Color(const int theColor) 11 | : mRed((theColor >> 16) & 0xFF), mGreen((theColor >> 8) & 0xFF), mBlue((theColor) & 0xFF), 12 | mAlpha((theColor >> 24) & 0xFF) { 13 | if (mAlpha == 0) mAlpha = 0xff; 14 | } 15 | 16 | Color::Color(const int theColor, const int theAlpha) 17 | : mRed((theColor >> 16) & 0xFF), mGreen((theColor >> 8) & 0xFF), mBlue((theColor) & 0xFF), mAlpha(theAlpha) {} 18 | 19 | Color::Color(const int theRed, const int theGreen, const int theBlue, const int theAlpha) 20 | : mRed(theRed), mGreen(theGreen), mBlue(theBlue), mAlpha(theAlpha) {} 21 | 22 | Color::Color(const SexyRGBA &theColor) : mRed(theColor.r), mGreen(theColor.g), mBlue(theColor.b), mAlpha(theColor.a) {} 23 | 24 | Color::Color(const uint8_t *theElements) 25 | : mRed(theElements[0]), mGreen(theElements[1]), mBlue(theElements[2]), mAlpha(0xFF) {} 26 | 27 | Color::Color(const int *theElements) 28 | : mRed(theElements[0]), mGreen(theElements[1]), mBlue(theElements[2]), mAlpha(0xFF) {} 29 | 30 | int Color::GetRed() const { return mRed; } 31 | 32 | int Color::GetGreen() const { return mGreen; } 33 | 34 | int Color::GetBlue() const { return mBlue; } 35 | 36 | int Color::GetAlpha() const { return mAlpha; } 37 | 38 | int &Color::operator[](const int theIdx) { 39 | static int aJunk = 0; 40 | 41 | switch (theIdx) { 42 | case 0: return mRed; 43 | case 1: return mGreen; 44 | case 2: return mBlue; 45 | case 3: return mAlpha; 46 | default: return aJunk; 47 | } 48 | } 49 | 50 | int Color::operator[](const int theIdx) const { 51 | switch (theIdx) { 52 | case 0: return mRed; 53 | case 1: return mGreen; 54 | case 2: return mBlue; 55 | case 3: return mAlpha; 56 | default: return 0; 57 | } 58 | } 59 | 60 | uint32_t Color::ToInt() const { return (mAlpha << 24) | (mRed << 16) | (mGreen << 8) | (mBlue); } 61 | 62 | SexyRGBA Color::ToRGBA() const { 63 | SexyRGBA anRGBA; 64 | anRGBA.r = mRed; 65 | anRGBA.g = mGreen; 66 | anRGBA.b = mBlue; 67 | anRGBA.a = mAlpha; 68 | 69 | return anRGBA; 70 | } 71 | 72 | bool Sexy::operator==(const Color &theColor1, const Color &theColor2) { 73 | return (theColor1.mRed == theColor2.mRed) && (theColor1.mGreen == theColor2.mGreen) && 74 | (theColor1.mBlue == theColor2.mBlue) && (theColor1.mAlpha == theColor2.mAlpha); 75 | } 76 | 77 | bool Sexy::operator!=(const Color &theColor1, const Color &theColor2) { 78 | return (theColor1.mRed != theColor2.mRed) || (theColor1.mGreen != theColor2.mGreen) || 79 | (theColor1.mBlue != theColor2.mBlue) || (theColor1.mAlpha != theColor2.mAlpha); 80 | } 81 | -------------------------------------------------------------------------------- /src/lawn/widget/AwardScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef __AWARDSCREEN_H__ 2 | #define __AWARDSCREEN_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/widget/Widget.h" 6 | using namespace Sexy; 7 | 8 | class LawnApp; 9 | class GameButton; 10 | 11 | class AchievementScreenItem { 12 | public: 13 | int mId; //+GOTY @Patoke: 0x00 14 | int mStartAnimTime; //+GOTY @Patoke: 0x04 15 | int mEndAnimTime; //+GOTY @Patoke: 0x08 16 | int mDestY; //+GOTY @Patoke: 0x0C 17 | int mStartY; //+GOTY @Patoke: 0x10 18 | int mY; //+GOTY @Patoke: 0x14 19 | }; 20 | 21 | class AwardScreen : public Widget { 22 | private: 23 | enum { AwardScreen_Start = 100, AwardScreen_Menu = 101 }; 24 | 25 | public: 26 | GameButton *mStartButton; //+0x88 27 | GameButton *mMenuButton; //+0x8C 28 | LawnApp *mApp; //+0x90 29 | int mFadeInCounter; //+0x94 30 | AwardType mAwardType; //+0x98 GOTY @Patoke: 0xB8 31 | GameButton *mContinueButton; //+GOTY @Patoke: 0xA8 32 | bool mShowStartButtonAfterAchievements; //+GOTY @Patoke: 0xAC 33 | bool mShowMenuButtonAfterAchievements; //+GOTY @Patoke: 0xAD 34 | int mAchievementAnimTime; //+GOTY @Patoke: 0xBC 35 | bool mShowingAchievements; //+GOTY @Patoke: 0xD8 36 | std::vector mAchievementItems; //+GOTY @Patoke: 0xC0 37 | 38 | public: 39 | // @Patoke: added argument 40 | AwardScreen(LawnApp *theApp, AwardType theAwardType, bool theShowingAchievements = false); 41 | ~AwardScreen() override; 42 | 43 | /*inline*/ bool IsPaperNote() const; 44 | 45 | void Resize(int theX, int theY, int theWidth, int theHeight) override { 46 | Widget::Resize(theX, theY, theWidth, theHeight); 47 | } 48 | 49 | static void 50 | DrawBottom(Graphics *g, const SexyString &theTitle, const SexyString &theAward, const SexyString &theMessage); 51 | void DrawAwardSeed(Graphics *g) const; 52 | void Draw(Graphics *g) override; 53 | void Update() override; 54 | void AddedToManager(WidgetManager *theWidgetManager) override { Widget::AddedToManager(theWidgetManager); } 55 | void RemovedFromManager(WidgetManager *theWidgetManager) override { Widget::RemovedFromManager(theWidgetManager); } 56 | void KeyChar(char theChar) override; 57 | void StartButtonPressed() const; 58 | void MouseDown(int x, int y, int theClickCount) override; 59 | void MouseUp(int x, int y, int theClickCount) override; 60 | // @Patoke: implement functions 61 | void DrawAchievements(Graphics *g) const; 62 | void AchievementsContinuePressed(); 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/framework/misc/memmgr.h: -------------------------------------------------------------------------------- 1 | #ifndef __SEXYMEMMGR_H__ 2 | #define __SEXYMEMMGR_H__ 3 | 4 | ////////////////////////////////////////////////////////////////////////// 5 | // HOW TO USE THIS FILE 6 | // 7 | // In the desired .CPP file (NOT header file), AFTER ALL of your 8 | // #include declarations, do a #include "memmgr.h" or whatever you renamed 9 | // this file to. It's very important that you do it only in the .cpp and 10 | // after every other include file, otherwise it won't compile. The memory leaks 11 | // will appear in a file called mem_leaks.txt and they will also be printed out 12 | // in the output window when the program exits. 13 | // 14 | ////////////////////////////////////////////////////////////////////////// 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | extern void SexyDumpUnfreed(); 21 | 22 | #if defined(SEXY_MEMTRACE) && !defined(RELEASEFINAL) 23 | 24 | /************************************************************************/ 25 | /* DO NOT CALL THESE TWO METHODS DIRECTLY */ 26 | /************************************************************************/ 27 | void SexyMemAddTrack(void *addr, int asize, const char *fname, int lnum); 28 | void SexyMemRemoveTrack(void *addr); 29 | 30 | // Replacement for the standard "new" operator, records size of allocation and 31 | // the file/line number it was on 32 | inline void *__cdecl operator new(unsigned int size, const char *file, int line) { 33 | void *ptr = (void *)malloc(size); 34 | SexyMemAddTrack(ptr, size, file, line); 35 | return (ptr); 36 | } 37 | 38 | // Same as above, but for arrays 39 | inline void *__cdecl operator new[](unsigned int size, const char *file, int line) { 40 | void *ptr = (void *)malloc(size); 41 | SexyMemAddTrack(ptr, size, file, line); 42 | return (ptr); 43 | } 44 | 45 | // These single argument new operators allow vc6 apps to compile without errors 46 | inline void *__cdecl operator new(unsigned int size) { 47 | void *ptr = (void *)malloc(size); 48 | return (ptr); 49 | } 50 | 51 | inline void *__cdecl operator new[](unsigned int size) { 52 | void *ptr = (void *)malloc(size); 53 | return (ptr); 54 | } 55 | 56 | // custom delete operators 57 | inline void __cdecl operator delete(void *p) { 58 | SexyMemRemoveTrack(p); 59 | free(p); 60 | } 61 | 62 | inline void __cdecl operator delete[](void *p) { 63 | SexyMemRemoveTrack(p); 64 | free(p); 65 | } 66 | 67 | // needed in case in the constructor of the class we're newing, it throws an exception 68 | inline void __cdecl operator delete(void *pMem, const char *file, int line) { free(pMem); } 69 | 70 | inline void __cdecl operator delete[](void *pMem, const char *file, int line) { free(pMem); } 71 | 72 | #define DEBUG_NEW new (__FILE__, __LINE__) 73 | #define new DEBUG_NEW 74 | 75 | #endif // SEXY_MEMTRACE 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/todlib/TodDebug.cpp: -------------------------------------------------------------------------------- 1 | #include "TodDebug.h" 2 | #include "TodCommon.h" 3 | #include "framework/SexyAppBase.h" 4 | #include "misc/Debug.h" 5 | #include 6 | #include 7 | 8 | using namespace Sexy; 9 | 10 | TodLogger* gTodLogger = nullptr; 11 | 12 | TodLogger::TodLogger() { 13 | mBuffer.resize(kBufferSize); 14 | gTodLogger = this; 15 | } 16 | 17 | TodLogger::~TodLogger() { 18 | TodLog("Ended at {:%Y-%m-%d %H:%M:%S}\n", std::chrono::system_clock::now()); 19 | gTodLogger = nullptr; 20 | 21 | mLogFile.write(mBuffer.data(), mBufferOffset); 22 | mLogFile.flush(); 23 | mLogFile.close(); 24 | } 25 | 26 | bool TodLogger::Init() { 27 | MkDir(GetAppDataFolder() + "userdata"); 28 | const auto aStart = std::chrono::system_clock::now(); 29 | const std::string aRelativeUserPath = GetAppDataFolder() + "userdata/"; 30 | const auto aLogFileName = fmt::format("{}log_{}.txt", GetFullPath(aRelativeUserPath), std::chrono::system_clock::to_time_t(aStart)); 31 | 32 | mLogFile.open(aLogFileName, std::ios::app); 33 | TodLog("Started at {}\n", aStart); 34 | 35 | return true; 36 | } 37 | 38 | void TodLogger::LogString(const std::string &theMsg) { 39 | if (theMsg.empty()) { 40 | return; 41 | } 42 | 43 | if (theMsg.length() > kBufferSize / 2) { 44 | mFileMutex.lock(); 45 | mLogFile.write(mBuffer.data(), mBufferOffset); 46 | mLogFile.write(theMsg.data(), theMsg.size()); 47 | mBufferOffset = 0; 48 | mFileMutex.unlock(); 49 | } 50 | 51 | for (size_t aRetry = 0; aRetry < kMaxDelayCycle; aRetry++) { 52 | size_t aOffset = mBufferOffset.fetch_add(theMsg.size()); 53 | if (aOffset >= kBufferSize) continue; 54 | if (aOffset + theMsg.size() > kBufferSize) { 55 | mFileMutex.lock(); 56 | mLogFile.write(mBuffer.data(), aOffset); 57 | mBufferOffset = 0; 58 | mFileMutex.unlock(); 59 | } else { 60 | std::ranges::copy(theMsg, mBuffer.begin() + aOffset); 61 | break; 62 | } 63 | } 64 | } 65 | 66 | // 0x514EA0 67 | void TodErrorMessageBox(const char *theMessage, const char *theTitle) { 68 | throw std::runtime_error("Error Box\n--" + std::string(theTitle) + "--\n" + theMessage); 69 | } 70 | 71 | void TodTraceMemory() {} 72 | 73 | void *TodMalloc(int theSize) { 74 | TOD_ASSERT(theSize > 0); 75 | return malloc(theSize); 76 | } 77 | 78 | void TodFree(void *theBlock) { 79 | if (theBlock != nullptr) { 80 | free(theBlock); 81 | } 82 | } 83 | 84 | void TodLogString(const std::string &theMsg) { 85 | if (gTodLogger != nullptr) { 86 | gTodLogger->LogString(theMsg); 87 | } 88 | } 89 | 90 | void TodHesitationTrace(...) {} 91 | 92 | void TodAssertInitForApp() 93 | { 94 | if (gTodLogger != nullptr) { 95 | gTodLogger->Init(); 96 | } 97 | } -------------------------------------------------------------------------------- /src/framework/widget/DialogButton.cpp: -------------------------------------------------------------------------------- 1 | #include "DialogButton.h" 2 | #include "WidgetManager.h" 3 | #include "graphics/Font.h" 4 | 5 | using namespace Sexy; 6 | 7 | static int gDialogButtonColors[][3] = { 8 | {255, 255, 255}, 9 | {255, 255, 255}, 10 | {0, 0, 0 }, 11 | {255, 255, 255}, 12 | {132, 132, 132}, 13 | {212, 212, 212} 14 | }; 15 | 16 | DialogButton::DialogButton(Image *theComponentImage, int theId, ButtonListener *theListener) 17 | : ButtonWidget(theId, theListener) { 18 | mComponentImage = theComponentImage; 19 | 20 | mTextOffsetX = mTextOffsetY = 0; 21 | mTranslateX = mTranslateY = 1; 22 | mDoFinger = true; 23 | 24 | Widget::SetColors(gDialogButtonColors, NUM_COLORS); 25 | } 26 | 27 | void DialogButton::Draw(Graphics *g) { 28 | if (mBtnNoDraw) return; 29 | 30 | if (mComponentImage == nullptr) { 31 | ButtonWidget::Draw(g); 32 | return; 33 | } 34 | 35 | /* FIXME 36 | if ((mFont == NULL) && (mLabel.length() > 0)) 37 | mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 12, true); 38 | */ 39 | 40 | bool doTranslate = IsButtonDown(); 41 | 42 | if (mNormalRect.mWidth == 0) { 43 | if (doTranslate) g->Translate(mTranslateX, mTranslateY); 44 | 45 | g->DrawImageBox(Rect(0, 0, mWidth, mHeight), mComponentImage); 46 | } else { 47 | if (mDisabled && (mDisabledRect.mWidth > 0) && (mDisabledRect.mHeight > 0)) 48 | g->DrawImageBox(mDisabledRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 49 | else if (IsButtonDown()) g->DrawImageBox(mDownRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 50 | else if ((mOverAlpha > 0)) { 51 | if (mOverAlpha < 1) g->DrawImageBox(mNormalRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 52 | 53 | g->SetColorizeImages(true); 54 | g->SetColor(Color(255, 255, 255, static_cast(mOverAlpha * 255))); 55 | g->DrawImageBox(mOverRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 56 | g->SetColorizeImages(false); 57 | } else if (mIsOver) g->DrawImageBox(mOverRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 58 | else g->DrawImageBox(mNormalRect, Rect(0, 0, mWidth, mHeight), mComponentImage); 59 | 60 | if (doTranslate) g->Translate(mTranslateX, mTranslateY); 61 | } 62 | 63 | if (mFont != nullptr) { 64 | g->SetFont(mFont); 65 | 66 | if (mIsOver) g->SetColor(mColors[COLOR_LABEL_HILITE]); 67 | else g->SetColor(mColors[COLOR_LABEL]); 68 | 69 | int aFontX = (mWidth - mFont->StringWidth(mLabel)) / 2; 70 | int aFontY = (mHeight + mFont->GetAscent() - mFont->GetAscentPadding() - mFont->GetAscent() / 6 - 1) / 2; 71 | 72 | g->DrawString(mLabel, aFontX + mTextOffsetX, aFontY + mTextOffsetY); 73 | } 74 | 75 | if (doTranslate) g->Translate(-mTranslateX, -mTranslateY); 76 | } 77 | -------------------------------------------------------------------------------- /src/compiler/map.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "hash.h" 3 | #include 4 | 5 | namespace compiler { 6 | template class OrderedMap { 7 | using MapItem = std::tuple; 8 | 9 | struct HashItemComparator { 10 | constexpr bool operator()(const MapItem &lhs, const MapItem &rhs) const { 11 | return std::get<0>(lhs) < std::get<0>(rhs); 12 | } 13 | }; 14 | 15 | std::array arr; 16 | 17 | public: 18 | constexpr explicit OrderedMap(std::tuple const (&raw)[Size]) noexcept : arr() { 19 | for (size_t i = 0; i < Size; ++i) { 20 | auto [idx, value] = raw[i]; 21 | arr[i] = {idx, value}; 22 | } 23 | compiler::sort(arr, HashItemComparator()); 24 | } 25 | 26 | constexpr std::optional find(T idx) const { 27 | const auto it = std::ranges::lower_bound(arr, std::make_tuple(idx, V{}), HashItemComparator()); 28 | 29 | if (it != arr.end() && std::get<0>(*it) == idx) { 30 | return std::get<1>(*it); 31 | } 32 | 33 | return std::nullopt; 34 | } 35 | 36 | consteval V operator[](T idx) const { 37 | auto v = find(idx); 38 | if (v.has_value()) { 39 | return v.value(); 40 | } 41 | static_assert(!std::is_same_v, "Key not found"); 42 | return V{}; 43 | } 44 | }; 45 | 46 | template class OrderedHashMap { 47 | using HashFnMapItem = std::tuple())), V>; 48 | 49 | struct HashItemComparator { 50 | constexpr bool operator()(const HashFnMapItem &lhs, const HashFnMapItem &rhs) const { 51 | return std::get<0>(lhs) < std::get<0>(rhs); 52 | } 53 | }; 54 | 55 | std::array arr; 56 | 57 | public: 58 | constexpr explicit OrderedHashMap(std::tuple const (&raw)[Size]) noexcept : arr() { 59 | for (size_t i = 0; i < Size; ++i) { 60 | auto [name, value] = raw[i]; 61 | auto hash = compiler::hash(name); 62 | arr[i] = {hash, value}; 63 | } 64 | compiler::sort(arr, HashItemComparator()); 65 | } 66 | 67 | constexpr std::optional find(T str) const { 68 | auto hash = compiler::hash(str); 69 | const auto it = std::ranges::lower_bound(arr, std::make_tuple(hash, V{}), HashItemComparator()); 70 | 71 | if (it != arr.end() && std::get<0>(*it) == hash) { 72 | return std::get<1>(*it); 73 | } 74 | 75 | return std::nullopt; 76 | } 77 | 78 | consteval V operator[](T str) const { 79 | auto v = find(str); 80 | if (v.has_value()) { 81 | return v.value(); 82 | } 83 | static_assert(!std::is_same_v, "Key not found"); 84 | return V{}; 85 | } 86 | }; 87 | } // namespace compiler -------------------------------------------------------------------------------- /src/framework/widget/WidgetContainer.h: -------------------------------------------------------------------------------- 1 | #ifndef __WIDGETCONTAINER_H__ 2 | #define __WIDGETCONTAINER_H__ 3 | 4 | #include "framework/Common.h" 5 | #include "framework/misc/Flags.h" 6 | #include "framework/misc/Rect.h" 7 | 8 | namespace Sexy { 9 | class Graphics; 10 | class Widget; 11 | class WidgetManager; 12 | 13 | using WidgetList = std::list; 14 | 15 | class WidgetContainer { 16 | public: 17 | WidgetList mWidgets; 18 | WidgetManager *mWidgetManager; 19 | WidgetContainer *mParent; 20 | 21 | bool mUpdateIteratorModified; 22 | WidgetList::iterator mUpdateIterator; 23 | uint32_t mLastWMUpdateCount; 24 | int mUpdateCnt; 25 | bool mDirty; 26 | int mX; 27 | int mY; 28 | int mWidth; 29 | int mHeight; 30 | bool mHasAlpha; 31 | bool mClip; 32 | FlagsMod mWidgetFlagsMod; 33 | int mPriority; 34 | int mZOrder; 35 | 36 | public: 37 | Widget *GetWidgetAtHelper(int x, int y, int theFlags, bool *found, int *theWidgetX, int *theWidgetY); 38 | bool IsBelowHelper(Widget *theWidget1, Widget *theWidget2, bool *found); 39 | void InsertWidgetHelper(const WidgetList::iterator &where, Widget *theWidget); 40 | 41 | public: 42 | WidgetContainer(); 43 | virtual ~WidgetContainer(); 44 | 45 | virtual Rect GetRect(); 46 | virtual bool Intersects(WidgetContainer *theWidget); 47 | 48 | virtual void AddWidget(Widget *theWidget); 49 | virtual void RemoveWidget(Widget *theWidget); 50 | virtual bool HasWidget(Widget *theWidget); 51 | virtual void DisableWidget(Widget *theWidget); 52 | virtual void RemoveAllWidgets(bool doDelete = false, bool recursive = false); 53 | 54 | virtual void SetFocus(Widget *theWidget); 55 | virtual bool IsBelow(Widget *theWidget1, Widget *theWidget2); 56 | virtual void MarkAllDirty(); 57 | virtual void BringToFront(Widget *theWidget); 58 | virtual void BringToBack(Widget *theWidget); 59 | virtual void PutBehind(Widget *theWidget, Widget *theRefWidget); 60 | virtual void PutInfront(Widget *theWidget, Widget *theRefWidget); 61 | virtual Point GetAbsPos(); // relative to top level 62 | 63 | virtual void MarkDirty(); 64 | virtual void MarkDirtyFull(); 65 | virtual void MarkDirtyFull(WidgetContainer *theWidget); 66 | virtual void MarkDirty(WidgetContainer *theWidget); 67 | 68 | virtual void AddedToManager(WidgetManager *theWidgetManager); 69 | virtual void RemovedFromManager(WidgetManager *theWidgetManager); 70 | 71 | virtual void Update(); 72 | virtual void UpdateAll(ModalFlags *theFlags); 73 | // virtual void UpdateF(float theFrac); 74 | virtual void UpdateFAll(ModalFlags *theFlags, float theFrac); 75 | virtual void Draw(Graphics *g); 76 | virtual void DrawAll(ModalFlags *theFlags, Graphics *g); 77 | virtual void SysColorChangedAll(); 78 | virtual void SysColorChanged(); 79 | }; 80 | }; // namespace Sexy 81 | 82 | #endif //__WIDGETCONTAINER_H__ 83 | -------------------------------------------------------------------------------- /src/framework/misc/DescParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __DESCPARSER_H__ 2 | #define __DESCPARSER_H__ 3 | 4 | #include "framework/Common.h" 5 | 6 | namespace Sexy { 7 | class DataElement { 8 | public: 9 | bool mIsList; 10 | 11 | public: 12 | DataElement(); 13 | virtual ~DataElement(); 14 | 15 | virtual DataElement *Duplicate() = 0; 16 | }; 17 | 18 | class SingleDataElement : public DataElement { 19 | public: 20 | std::string mString; 21 | 22 | public: 23 | SingleDataElement(); 24 | SingleDataElement(const std::string theString); 25 | ~SingleDataElement() override; 26 | 27 | DataElement *Duplicate() override; 28 | }; 29 | 30 | using ElementVector = std::vector; 31 | 32 | class ListDataElement : public DataElement { 33 | public: 34 | ElementVector mElementVector; 35 | 36 | public: 37 | ListDataElement(); 38 | ListDataElement(const ListDataElement &theListDataElement); 39 | ~ListDataElement() override; 40 | 41 | ListDataElement &operator=(const ListDataElement &theListDataElement); 42 | 43 | DataElement *Duplicate() override; 44 | }; 45 | 46 | using DataElementMap = std::map; 47 | using StringVector = std::vector; 48 | using IntVector = std::vector; 49 | using DoubleVector = std::vector; 50 | 51 | class DescParser { 52 | public: 53 | enum { CMDSEP_SEMICOLON = 1, CMDSEP_NO_INDENT = 2 }; 54 | 55 | public: 56 | int mCmdSep; 57 | 58 | std::string mError; 59 | int mCurrentLineNum; 60 | std::string mCurrentLine; 61 | DataElementMap mDefineMap; 62 | 63 | public: 64 | virtual bool Error(const std::string &theError); 65 | virtual DataElement *Dereference(const std::string &theString); 66 | bool IsImmediate(const std::string &theString); 67 | std::string Unquote(const std::string &theQuotedString); 68 | bool GetValues(ListDataElement *theSource, ListDataElement *theValues); 69 | std::string DataElementToString(DataElement *theDataElement); 70 | bool DataToString(DataElement *theSource, std::string *theString); 71 | bool DataToInt(DataElement *theSource, int *theInt); 72 | bool DataToStringVector(DataElement *theSource, StringVector *theStringVector); 73 | bool DataToList(DataElement *theSource, ListDataElement *theValues); 74 | bool DataToIntVector(DataElement *theSource, IntVector *theIntVector); 75 | bool DataToDoubleVector(DataElement *theSource, DoubleVector *theDoubleVector); 76 | bool ParseToList(const std::string &theString, ListDataElement *theList, bool expectListEnd, int *theStringPos); 77 | bool ParseDescriptorLine(const std::string &theDescriptorLine); 78 | 79 | // You must implement this one 80 | virtual bool HandleCommand(const ListDataElement &theParams) = 0; 81 | 82 | public: 83 | DescParser(); 84 | virtual ~DescParser(); 85 | 86 | bool LoadDescriptor(const std::string &theFileName); 87 | }; 88 | } // namespace Sexy 89 | 90 | #endif //__DESCPARSER_H__ 91 | -------------------------------------------------------------------------------- /src/framework/widget/ListWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __LISTWIDGET_H__ 2 | #define __LISTWIDGET_H__ 3 | 4 | #include "ScrollListener.h" 5 | #include "Widget.h" 6 | 7 | namespace Sexy { 8 | using SexyStringVector = std::vector; 9 | using ColorVector = std::vector; 10 | 11 | class ScrollbarWidget; 12 | class ListListener; 13 | class _Font; 14 | 15 | class ListWidget : public Widget, public ScrollListener { 16 | public: 17 | enum { JUSTIFY_LEFT = 0, JUSTIFY_CENTER, JUSTIFY_RIGHT }; 18 | 19 | enum { 20 | COLOR_BKG = 0, 21 | COLOR_OUTLINE, 22 | COLOR_TEXT, 23 | COLOR_HILITE, 24 | COLOR_SELECT, 25 | COLOR_SELECT_TEXT, 26 | }; 27 | 28 | public: 29 | int mId; 30 | _Font *mFont; 31 | ScrollbarWidget *mScrollbar; 32 | int mJustify; 33 | 34 | SexyStringVector mLines; 35 | ColorVector mLineColors; 36 | double mPosition; 37 | double mPageSize; 38 | int mHiliteIdx; 39 | int mSelectIdx; 40 | ListListener *mListListener; 41 | ListWidget *mParent; 42 | ListWidget *mChild; 43 | bool mSortFromChild; 44 | bool mDrawOutline; 45 | int mMaxNumericPlaces; 46 | int mItemHeight; 47 | 48 | bool mDrawSelectWhenHilited; 49 | bool mDoFingerWhenHilited; 50 | 51 | void SetHilite(int theHiliteIdx, bool notifyListener = false); 52 | 53 | public: 54 | ListWidget(int theId, _Font *theFont, ListListener *theListListener); 55 | ~ListWidget() override; 56 | 57 | void RemovedFromManager(WidgetManager *theManager) override; 58 | 59 | virtual SexyString GetSortKey(int theIdx); 60 | virtual void Sort(bool ascending); 61 | virtual SexyString GetStringAt(int theIdx); 62 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 63 | virtual int AddLine(const SexyString &theLine, bool alphabetical); 64 | virtual void SetLine(int theIdx, const SexyString &theString); 65 | virtual int GetLineCount(); 66 | virtual int GetLineIdx(const SexyString &theLine); 67 | virtual void SetColor(const SexyString &theLine, const Color &theColor); 68 | void SetColor(int theIdx, const Color &theColor) override; 69 | virtual void SetLineColor(int theIdx, const Color &theColor); 70 | virtual void RemoveLine(int theIdx); 71 | virtual void RemoveAll(); 72 | virtual int GetOptimalWidth(); 73 | virtual int GetOptimalHeight(); 74 | void OrderInManagerChanged() override; 75 | void Draw(Graphics *g) override; 76 | void ScrollPosition(int theId, double thePosition) override; 77 | void MouseMove(int x, int y) override; 78 | void MouseWheel(int theDelta) override; 79 | void MouseDown(int x, int y, int theClickCount) override { Widget::MouseDown(x, y, theClickCount); } 80 | void MouseDown(int x, int y, int theBtnNum, int theClickCount) override; 81 | void MouseLeave() override; 82 | virtual void SetSelect(int theSelectIdx); 83 | }; 84 | } // namespace Sexy 85 | 86 | #endif // __LISTWIDGET_H__ 87 | -------------------------------------------------------------------------------- /src/lawn/widget/LawnDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __LAWNDIALOG_H__ 2 | #define __LAWNDIALOG_H__ 3 | 4 | #include "framework/widget/Dialog.h" 5 | #include "todlib/TodCommon.h" 6 | 7 | constexpr const int DIALOG_HEADER_OFFSET = 45; 8 | 9 | class LawnApp; 10 | class LawnDialog; 11 | class Reanimation; 12 | class LawnStoneButton; 13 | class ReanimationWidget; 14 | 15 | namespace Sexy { 16 | class Checkbox; 17 | class DialogButton; 18 | class CheckboxListener; 19 | } // namespace Sexy 20 | 21 | // using namespace std; 22 | using namespace Sexy; 23 | 24 | class ReanimationWidget : public Widget { 25 | public: 26 | LawnApp *mApp; //+0x88 27 | Reanimation *mReanim; //+0x8C 28 | LawnDialog *mLawnDialog; //+0x90 29 | float mPosX; //+0x94 30 | float mPosY; //+0x98 31 | 32 | public: 33 | ReanimationWidget(); 34 | ~ReanimationWidget() override; 35 | 36 | /*inline*/ void Dispose(); 37 | void Draw(Graphics *) override; 38 | void Update() override; 39 | void AddReanimation(float x, float y, ReanimationType theReanimationType); 40 | }; 41 | 42 | class LawnDialog : public Dialog { 43 | public: 44 | LawnApp *mApp; //+0x150 45 | int mButtonDelay; //+0x154 46 | ReanimationWidget *mReanimation; //+0x158 47 | bool mDrawStandardBack; //+0x15C 48 | LawnStoneButton *mLawnYesButton; //+0x160 49 | LawnStoneButton *mLawnNoButton; //+0x164 50 | bool mTallBottom; //+0x168 51 | bool mVerticalCenterText; //+0x169 52 | 53 | public: 54 | LawnDialog( 55 | LawnApp *theApp, int theId, bool isModal, const SexyString &theDialogHeader, const SexyString &theDialogLines, 56 | const SexyString &theDialogFooter, int theButtonMode 57 | ); 58 | ~LawnDialog() override; 59 | 60 | int GetLeft() const; 61 | int GetWidth() const; 62 | int GetTop(); 63 | virtual void SetButtonDelay(int theDelay); 64 | void Update() override; 65 | void ButtonPress(int theId) override; 66 | void ButtonDepress(int theId) override; 67 | virtual void CheckboxChecked(); 68 | void KeyDown(KeyCode theKey) override; 69 | void AddedToManager(WidgetManager *theWidgetManager) override; 70 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 71 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 72 | void Draw(Graphics *g) override; 73 | void CalcSize(int theExtraX, int theExtraY); 74 | }; 75 | 76 | class GameOverDialog : public LawnDialog { 77 | public: 78 | DialogButton *mMenuButton; 79 | 80 | public: 81 | GameOverDialog(const SexyString &theMessage, bool theShowChallengeName); 82 | ~GameOverDialog() override; 83 | 84 | void ButtonDepress(int theId) override; 85 | void AddedToManager(WidgetManager *theWidgetManager) override; 86 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 87 | void MouseDrag(int x, int y) override; 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/lawn/Projectile.h: -------------------------------------------------------------------------------- 1 | #ifndef __PROJECTILE_H__ 2 | #define __PROJECTILE_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "GameObject.h" 6 | 7 | class Plant; 8 | class Zombie; 9 | 10 | namespace Sexy { 11 | class Graphics; 12 | }; 13 | 14 | using namespace Sexy; 15 | 16 | class ProjectileDefinition { 17 | public: 18 | ProjectileType mProjectileType; 19 | int mImageRow; 20 | int mDamage; 21 | }; 22 | 23 | extern ProjectileDefinition gProjectileDefinition[NUM_PROJECTILES]; // 0x69F1C0 24 | 25 | class Projectile : public GameObject { 26 | public: 27 | int mFrame; //+0x24 28 | int mNumFrames; //+0x28 29 | int mAnimCounter; //+0x2C 30 | float mPosX; //+0x30 31 | float mPosY; //+0x34 32 | float mPosZ; //+0x38 33 | float mVelX; //+0x3C 34 | float mVelY; //+0x40 35 | float mVelZ; //+0x44 36 | float mAccZ; //+0x48 37 | float mShadowY; //+0x4C 38 | bool mDead; //+0x50 39 | int mAnimTicksPerFrame; //+0x54 40 | ProjectileMotion mMotionType; //+0x58 41 | ProjectileType mProjectileType; //+0x5C 42 | int mProjectileAge; //+0x60 43 | int mClickBackoffCounter; //+0x64 44 | float mRotation; //+0x68 45 | float mRotationSpeed; //+0x6C 46 | bool mOnHighGround; //+0x70 47 | int mDamageRangeFlags; //+0x74 48 | int mHitTorchwoodGridX; //+0x78 49 | AttachmentID mAttachmentID; //+0x7C 50 | float mCobTargetX; //+0x80 51 | int mCobTargetRow; //+0x84 52 | ZombieID mTargetZombieID; //+0x88 53 | int mLastPortalX; //+0x8C 54 | 55 | public: 56 | Projectile(); 57 | ~Projectile(); 58 | 59 | void ProjectileInitialize(int theX, int theY, int theRenderOrder, int theRow, ProjectileType theProjectileType); 60 | void Update(); 61 | void Draw(Graphics *g); 62 | void DrawShadow(Graphics *g); 63 | void Die(); 64 | void DoImpact(Zombie *theZombie); 65 | void UpdateMotion(); 66 | void CheckForCollision(); 67 | Zombie *FindCollisionTarget(); 68 | void UpdateLobMotion(); 69 | void CheckForHighGround(); 70 | bool CantHitHighGround() const; 71 | void DoSplashDamage(const Zombie *theZombie); 72 | ProjectileDefinition &GetProjectileDef(); 73 | unsigned int GetDamageFlags(Zombie *theZombie /* = nullptr*/); 74 | Rect GetProjectileRect(); 75 | void UpdateNormalMotion(); 76 | Plant *FindCollisionTargetPlant(); 77 | void ConvertToFireball(int theGridX); 78 | void ConvertToPea(int theGridX); 79 | bool IsSplashDamage(Zombie *theZombie /* = nullptr*/); 80 | void PlayImpactSound(Zombie *theZombie); 81 | bool IsZombieHitBySplash(Zombie *theZombie); 82 | bool PeaAboutToHitTorchwood(); 83 | }; 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/lawn/GridItem.h: -------------------------------------------------------------------------------- 1 | #ifndef __GRIDITEM_H__ 2 | #define __GRIDITEM_H__ 3 | 4 | #include "ConstEnums.h" 5 | 6 | #define NUM_MOTION_TRAIL_FRAMES 12 7 | 8 | class LawnApp; 9 | class Board; 10 | class Zombie; 11 | 12 | namespace Sexy { 13 | class Graphics; 14 | }; 15 | 16 | class MotionTrailFrame { 17 | public: 18 | float mPosX; 19 | float mPosY; 20 | float mAnimTime; 21 | }; 22 | 23 | class GridItem { 24 | public: 25 | LawnApp *mApp; //+0x0 26 | Board *mBoard; //+0x4 27 | GridItemType mGridItemType; //+0x8 28 | GridItemState mGridItemState; //+0xC 29 | int mGridX; //+0x10 30 | int mGridY; //+0x14 31 | int mGridItemCounter; //+0x18 32 | int mRenderOrder; //+0x1C 33 | bool mDead; //+0x20 34 | float mPosX; //+0x24 35 | float mPosY; //+0x28 36 | float mGoalX; //+0x2C 37 | float mGoalY; //+0x30 38 | ReanimationID mGridItemReanimID; //+0x34 39 | ParticleSystemID mGridItemParticleID; //+0x38 40 | ZombieType mZombieType; //+0x3C 41 | SeedType mSeedType; //+0x40 42 | ScaryPotType mScaryPotType; //+0x44 43 | bool mHighlighted; //+0x48 44 | int mTransparentCounter; //+0x4C 45 | int mSunCount; //+0x50 46 | MotionTrailFrame mMotionTrailFrames[NUM_MOTION_TRAIL_FRAMES]; //+0x54 47 | int mMotionTrailCount; //+0xE4 48 | 49 | public: 50 | GridItem(); 51 | 52 | void DrawLadder(Sexy::Graphics *g); 53 | void DrawCrater(Sexy::Graphics *g); 54 | void DrawGraveStone(Sexy::Graphics *g); 55 | void GridItemDie(); 56 | void AddGraveStoneParticles(); 57 | void DrawGridItem(Sexy::Graphics *g); 58 | void DrawGridItemOverlay(Sexy::Graphics *g) const; 59 | void OpenPortal(); 60 | void Update(); 61 | void ClosePortal(); 62 | void DrawScaryPot(Sexy::Graphics *g); 63 | void UpdateScaryPot(); 64 | void UpdatePortal(); 65 | void DrawSquirrel(Sexy::Graphics *g); 66 | void UpdateRake(); 67 | Zombie *RakeFindZombie(); 68 | void DrawIZombieBrain(Sexy::Graphics *g); 69 | void UpdateBrain(); 70 | void DrawStinky(Sexy::Graphics *g); 71 | /*inline*/ bool IsOpenPortal(); 72 | }; 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/framework/graphics/VkCommon.h: -------------------------------------------------------------------------------- 1 | #ifndef VK_COMMON_H 2 | #define VK_COMMON_H 3 | 4 | #include "Color.h" 5 | #include "compiler/array.h" 6 | #include 7 | #include 8 | #if defined(_WIN32) 9 | #define VK_USE_PLATFORM_WIN32_KHR 10 | #endif 11 | #include 12 | 13 | #if defined(NDEBUG) 14 | #define SCALE 2 15 | #else 16 | #define SCALE 1 17 | #endif 18 | 19 | namespace Vk { 20 | extern VkDevice device; 21 | 22 | class VkImage; 23 | 24 | constexpr int NUM_IMAGE_SWAPS = 3; 25 | 26 | constexpr VkFormat pixelFormat = VK_FORMAT_B8G8R8A8_UNORM; 27 | 28 | extern std::mutex renderMutex; 29 | 30 | extern VkQueue graphicsQueue; 31 | extern VkPipeline graphicsPipeline; 32 | extern VkPipeline computePipeline; 33 | extern VkPipeline graphicsPipelineAdditive; 34 | extern std::array imageCommandBuffers; 35 | extern VkRenderPass imagePass; 36 | extern std::array imageFences; 37 | 38 | extern VkDescriptorPool descriptorPool; 39 | extern VkDescriptorSetLayout descriptorSetLayout; 40 | 41 | // extern std::vector uniformBuffers; 42 | // extern VkBuffer vertexBuffer; 43 | // extern VkBuffer indexBuffer; 44 | 45 | extern VkPipelineLayout pipelineLayout; 46 | extern VkPipelineLayout computePipelineLayout; 47 | extern VkSampler textureSampler; 48 | extern VkSampler textureSamplerRepeat; 49 | 50 | extern uint32_t currentFrame; 51 | // extern VkImage* otherCachedImage; 52 | 53 | extern const std::vector indices; 54 | 55 | extern VkPhysicalDeviceProperties physicalDeviceProperties; 56 | 57 | VkImageView createImageView(::VkImage image, VkFormat format); 58 | 59 | struct ImagePushConstants { 60 | glm::vec4 vertices[4]; 61 | Sexy::SexyRGBA vertex_colors[4]; 62 | uint32_t is_quad; 63 | uint32_t filter; 64 | glm::vec2 filterOffset = glm::vec2(); 65 | }; 66 | 67 | struct ComputePushConstants { 68 | int32_t type; 69 | }; 70 | 71 | struct UniformBufferObject { 72 | glm::mat4 model; 73 | glm::mat4 view; 74 | glm::mat4 proj; 75 | }; 76 | 77 | void createBuffer( 78 | VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, 79 | VkDeviceMemory &bufferMemory 80 | ); 81 | 82 | uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); 83 | 84 | void flushCommandBuffer(); 85 | void copyBufferToImage( 86 | VkCommandBuffer commandBuffer, VkBuffer buffer, ::VkImage image, uint32_t width, uint32_t height 87 | ); 88 | void beginCommandBuffer(); 89 | 90 | struct deleteInfo { 91 | std::optional<::VkImage> image; 92 | std::optional view; 93 | std::optional framebuffer; 94 | std::optional memory; 95 | std::optional set; 96 | std::optional buffer; 97 | }; 98 | 99 | void doDeleteInfo(deleteInfo info); 100 | void deferredDelete(size_t idx); 101 | } // namespace Vk 102 | 103 | #endif // VK_COMMON_H 104 | -------------------------------------------------------------------------------- /src/framework/misc/Rect.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRectANGLE_H__ 2 | #define __TRectANGLE_H__ 3 | 4 | #include "Point.h" 5 | 6 | #include 7 | 8 | namespace Sexy { 9 | template class TRect { 10 | public: 11 | _T mX; 12 | _T mY; 13 | _T mWidth; 14 | _T mHeight; 15 | 16 | public: 17 | TRect(_T theX, _T theY, _T theWidth, _T theHeight) : mX(theX), mY(theY), mWidth(theWidth), mHeight(theHeight) {} 18 | 19 | /* 20 | TRect(const TRect<_T>& theTRect) : 21 | mX(theTRect.mX), mY(theTRect.mY), mWidth(theTRect.mWidth), mHeight(theTRect.mHeight) 22 | { 23 | } 24 | */ 25 | 26 | TRect() : mX(0), mY(0), mWidth(0), mHeight(0) {} 27 | 28 | bool Intersects(const TRect<_T> &theTRect) const { 29 | return !( 30 | (theTRect.mX + theTRect.mWidth <= mX) || (theTRect.mY + theTRect.mHeight <= mY) || 31 | (theTRect.mX >= mX + mWidth) || (theTRect.mY >= mY + mHeight) 32 | ); 33 | } 34 | 35 | TRect<_T> Intersection(const TRect<_T> &theTRect) const { 36 | _T x1 = std::max(mX, theTRect.mX); 37 | _T x2 = std::min(mX + mWidth, theTRect.mX + theTRect.mWidth); 38 | _T y1 = std::max(mY, theTRect.mY); 39 | _T y2 = std::min(mY + mHeight, theTRect.mY + theTRect.mHeight); 40 | if (((x2 - x1) < 0) || ((y2 - y1) < 0)) return TRect<_T>(0, 0, 0, 0); 41 | else return TRect<_T>(x1, y1, x2 - x1, y2 - y1); 42 | } 43 | 44 | TRect<_T> Union(const TRect<_T> &theTRect) { 45 | _T x1 = std::min(mX, theTRect.mX); 46 | _T x2 = std::max(mX + mWidth, theTRect.mX + theTRect.mWidth); 47 | _T y1 = std::min(mY, theTRect.mY); 48 | _T y2 = std::max(mY + mHeight, theTRect.mY + theTRect.mHeight); 49 | return TRect<_T>(x1, y1, x2 - x1, y2 - y1); 50 | } 51 | 52 | bool Contains(_T theX, _T theY) const { 53 | return ((theX >= mX) && (theX < mX + mWidth) && (theY >= mY) && (theY < mY + mHeight)); 54 | } 55 | 56 | bool Contains(const TPoint<_T> &thePoint) const { 57 | return ( 58 | (thePoint.mX >= mX) && (thePoint.mX < mX + mWidth) && (thePoint.mY >= mY) && (thePoint.mY < mY + mHeight) 59 | ); 60 | } 61 | 62 | void Offset(_T theX, _T theY) { 63 | mX += theX; 64 | mY += theY; 65 | } 66 | 67 | void Offset(const TPoint<_T> &thePoint) { 68 | mX += thePoint.mX; 69 | mY += thePoint.mY; 70 | } 71 | 72 | TRect Inflate(_T theX, _T theY) { 73 | mX -= theX; 74 | mWidth += theX * 2; 75 | mY -= theY; 76 | mHeight += theY * 2; 77 | 78 | return *this; 79 | } 80 | 81 | bool operator==(const TRect<_T> &theRect) const { 82 | return (mX == theRect.mX) && (mY == theRect.mY) && (mWidth == theRect.mWidth) && (mHeight == theRect.mHeight); 83 | } 84 | 85 | /* 86 | RECT ToRECT() const 87 | { 88 | RECT aRect = {mX, mY, mX + mWidth, mY + mHeight}; 89 | return aRect; 90 | }*/ 91 | }; 92 | 93 | using Rect = TRect; 94 | using FRect = TRect; 95 | } // namespace Sexy 96 | 97 | #endif //__TRectANGLE_H__ 98 | -------------------------------------------------------------------------------- /src/lawn/widget/AlmanacDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALMANACDIALOG_H__ 2 | #define __ALMANACDIALOG_H__ 3 | 4 | #include "LawnDialog.h" 5 | 6 | #define NUM_ALMANAC_SEEDS 49 7 | #define NUM_ALMANAC_ZOMBIES 26 8 | 9 | constexpr const float ALMANAC_PLANT_POSITION_X = 578.0f; 10 | constexpr const float ALMANAC_PLANT_POSITION_Y = 140.0f; 11 | constexpr const float ALMANAC_ZOMBIE_POSITION_X = 559.0f; 12 | constexpr const float ALMANAC_ZOMBIE_POSITION_Y = 175.0f; 13 | constexpr const int ALMANAC_INDEXPLANT_POSITION_X = 167; 14 | constexpr const int ALMANAC_INDEXPLANT_POSITION_Y = 255; 15 | constexpr const float ALMANAC_INDEXZOMBIE_POSITION_X = 535.0f; 16 | constexpr const float ALMANAC_INDEXZOMBIE_POSITION_Y = 215.0f; 17 | 18 | class Plant; 19 | class Zombie; 20 | class LawnApp; 21 | class GameButton; 22 | class Reanimation; 23 | 24 | class AlmanacDialog : public LawnDialog { 25 | private: 26 | enum { ALMANAC_BUTTON_CLOSE = 0, ALMANAC_BUTTON_PLANT = 1, ALMANAC_BUTTON_ZOMBIE = 2, ALMANAC_BUTTON_INDEX = 3 }; 27 | 28 | public: 29 | LawnApp *mApp; //+0x16C 30 | GameButton *mCloseButton; //+0x170 31 | GameButton *mIndexButton; //+0x174 32 | GameButton *mPlantButton; //+0x178 33 | GameButton *mZombieButton; //+0x17C 34 | AlmanacPage mOpenPage; //+0x180 35 | Reanimation *mReanim[4]{}; //+0x184 36 | SeedType mSelectedSeed; //+0x194 37 | ZombieType mSelectedZombie; //+0x198 38 | Plant *mPlant; //+0x19C 39 | Zombie *mZombie; //+0x1A0 40 | Zombie *mZombiePerfTest[400]{}; //+0x1A4 41 | 42 | public: 43 | AlmanacDialog(LawnApp *theApp); 44 | ~AlmanacDialog() override; 45 | 46 | void ClearPlantsAndZombies(); 47 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 48 | void SetupPlant(); 49 | void SetupZombie(); 50 | void SetPage(AlmanacPage thePage); 51 | void Update() override; 52 | void DrawIndex(Graphics *g) const; 53 | void DrawPlants(Graphics *g) const; 54 | void DrawZombies(Graphics *g) const; 55 | void Draw(Graphics *g) override; 56 | static void GetSeedPosition(SeedType theSeedType, int &x, int &y); 57 | SeedType SeedHitTest(int x, int y) const; 58 | /*inline*/ bool ZombieHasSilhouette(ZombieType theZombieType) const; 59 | bool ZombieIsShown(ZombieType theZombieType) const; 60 | bool ZombieHasDescription(ZombieType theZombieType) const; 61 | static void GetZombiePosition(ZombieType theZombieType, int &x, int &y); 62 | ZombieType ZombieHitTest(int x, int y) const; 63 | void MouseUp(int x, int y, int theClickCount) override; 64 | void MouseDown(int x, int y, int theClickCount) override; 65 | // virtual void KeyChar(char theChar); 66 | 67 | static ZombieType GetZombieType(int theIndex); 68 | /*inline*/ void ShowPlant(SeedType theSeedType); 69 | /*inline*/ void ShowZombie(ZombieType theZombieType); 70 | }; 71 | 72 | extern bool gZombieDefeated[NUM_ZOMBIE_TYPES]; 73 | 74 | /*inline*/ void AlmanacInitForPlayer(); 75 | /*inline*/ void AlmanacPlayerDefeatedZombie(ZombieType theZombieType); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/todlib/Trail.h: -------------------------------------------------------------------------------- 1 | #ifndef __TRAIL_H__ 2 | #define __TRAIL_H__ 3 | 4 | #include "TodParticle.h" 5 | 6 | #define MAX_TRAIL_TRIANGLES 38 7 | 8 | enum TrailType { TRAIL_NONE = -1, TRAIL_ICE, NUM_TRAILS }; 9 | 10 | enum TrailTracks { 11 | TRACK_WIDTH_OVER_LENGTH, 12 | TRACK_WIDTH_OVER_TIME, 13 | TRACK_ALPHA_OVER_LENGTH, 14 | TRACK_ALPHA_OVER_TIME, 15 | NUM_TRAIL_TRACKS 16 | }; 17 | 18 | enum TrailFlags { TRAIL_FLAG_LOOPS = 0 }; 19 | 20 | class TrailParams { 21 | public: 22 | TrailType mTrailType; 23 | const char *mTrailFileName; 24 | }; 25 | 26 | extern int gTrailParamArraySize; //[0x6A9F28] 27 | extern TrailParams *gTrailParamArray; //[0x6A9F2C] 28 | 29 | extern TrailParams gLawnTrailArray[static_cast(TrailType::NUM_TRAILS)]; // 0x6A19F4 30 | 31 | class TrailDefinition { 32 | public: 33 | Image *mImage; 34 | int mMaxPoints; 35 | float mMinPointDistance; 36 | int mTrailFlags; 37 | FloatParameterTrack mTrailDuration; 38 | FloatParameterTrack mWidthOverLength; 39 | FloatParameterTrack mWidthOverTime; 40 | FloatParameterTrack mAlphaOverLength; 41 | FloatParameterTrack mAlphaOverTime; 42 | 43 | public: 44 | TrailDefinition(); 45 | ~TrailDefinition(); 46 | }; 47 | 48 | bool TrailLoadADef(TrailDefinition *theTrailDef, const char *theTrailFileName); 49 | void TrailLoadDefinitions(TrailParams *theTrailParamArray, int theTrailParamArraySize); 50 | void TrailFreeDefinitions(); 51 | 52 | extern int gTrailDefCount; //[0x6A9F20] 53 | extern TrailDefinition *gTrailDefArray; //[0x6A9F24] 54 | 55 | // #################################################################################################### // 56 | 57 | class TrailPoint { 58 | public: 59 | SexyVector2 aPos; 60 | 61 | public: 62 | TrailPoint(); 63 | }; 64 | 65 | class TrailHolder; 66 | 67 | class Trail { 68 | public: 69 | TrailPoint mTrailPoints[20]; //+0x0 70 | int mNumTrailPoints; //+0xA0 71 | bool mDead; //+0xA4 72 | int mRenderOrder; //+0xA8 73 | int mTrailAge; //+0xAC 74 | int mTrailDuration; //+0xB0 75 | TrailDefinition *mDefinition; //+0xB4 76 | TrailHolder *mTrailHolder; //+0xB8 77 | float mTrailInterp[4]; //+0xBC 78 | SexyVector2 mTrailCenter; //+0xCC 79 | bool mIsAttachment; //+0xD4 80 | Color mColorOverride; //+0xD8 81 | 82 | public: 83 | Trail(); 84 | 85 | void Update(); 86 | void Draw(Graphics *g) const; 87 | void AddPoint(float x, float y); 88 | bool GetNormalAtPoint(int nIndex, SexyVector2 &theNormal) const; 89 | }; 90 | 91 | class TrailHolder { 92 | public: 93 | DataArray mTrails; 94 | 95 | public: 96 | TrailHolder() { ; } 97 | ~TrailHolder() { DisposeHolder(); } 98 | 99 | void InitializeHolder(); 100 | void DisposeHolder(); 101 | Trail *AllocTrail(int theRenderOrder, TrailType theTrailType); 102 | Trail *AllocTrailFromDef(int theRenderOrder, TrailDefinition *theDefinition); 103 | }; 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/framework/widget/EditWidget.h: -------------------------------------------------------------------------------- 1 | #ifndef __EDITWIDGET_H__ 2 | #define __EDITWIDGET_H__ 3 | 4 | #include "Widget.h" 5 | 6 | namespace Sexy { 7 | class _Font; 8 | class EditListener; 9 | 10 | class EditWidget : public Widget { 11 | public: 12 | enum { COLOR_BKG, COLOR_OUTLINE, COLOR_TEXT, COLOR_HILITE, COLOR_HILITE_TEXT, NUM_COLORS }; 13 | 14 | int mId; 15 | SexyString mString; 16 | SexyString mPasswordDisplayString; 17 | _Font *mFont; 18 | 19 | struct WidthCheck { 20 | _Font *mFont; 21 | int mWidth; 22 | }; 23 | 24 | using WidthCheckList = std::list; 25 | WidthCheckList mWidthCheckList; 26 | 27 | EditListener *mEditListener; 28 | bool mShowingCursor; 29 | bool mDrawSelOverride; // set this to true to draw selected text even when not in focus 30 | bool mHadDoubleClick; 31 | // Used to fix a bug with double clicking to hilite a word after the widget manager started calling mouse drag 32 | // before mouse down/up events 33 | int mCursorPos; 34 | int mHilitePos; 35 | int mBlinkAcc; 36 | int mBlinkDelay; 37 | int mLeftPos; 38 | int mMaxChars; 39 | int mMaxPixels; 40 | SexyChar mPasswordChar; 41 | 42 | SexyString mUndoString; 43 | int mUndoCursor; 44 | int mUndoHilitePos; 45 | int mLastModifyIdx; 46 | 47 | protected: 48 | virtual void ProcessKey(KeyCode theKey, SexyChar theChar); 49 | SexyString &GetDisplayString(); 50 | virtual void HiliteWord(); 51 | void UpdateCaretPos(); 52 | 53 | public: 54 | virtual void SetFont(_Font *theFont, _Font *theWidthCheckFont = NULL); 55 | virtual void SetText(const SexyString &theText, bool leftPosToZero = true); 56 | virtual bool IsPartOfWord(SexyChar theChar); 57 | virtual int GetCharAt(int x, int y); 58 | 59 | void Resize(int theX, int theY, int theWidth, int theHeight) override; 60 | void Draw(Graphics *g) override; // Already translated; 61 | 62 | void Update() override; 63 | void MarkDirty() override; 64 | 65 | bool WantsFocus() override; 66 | void GotFocus() override; 67 | void LostFocus() override; 68 | virtual void FocusCursor(bool bigJump); 69 | 70 | void KeyDown(KeyCode theKey) override; 71 | void KeyChar(SexyChar theChar) override; 72 | 73 | void MouseDown(int x, int y, int theClickCount) override { Widget::MouseDown(x, y, theClickCount); } 74 | void MouseDown(int x, int y, int theBtnNum, int theClickCount) override; 75 | void MouseUp(int x, int y) override { Widget::MouseUp(x, y); } 76 | void MouseUp(int x, int y, int theClickCount) override { Widget::MouseUp(x, y, theClickCount); } 77 | void MouseUp(int x, int y, int theBtnNum, int theClickCount) override; 78 | void MouseDrag(int x, int y) override; 79 | void MouseEnter() override; 80 | void MouseLeave() override; 81 | void ClearWidthCheckFonts(); 82 | void AddWidthCheckFont(_Font *theFont, int theMaxPixels = -1); // defaults to mMaxPixels 83 | void EnforceMaxPixels(); 84 | 85 | public: 86 | EditWidget(int theId, EditListener *theEditListener); 87 | ~EditWidget() override; 88 | }; 89 | } // namespace Sexy 90 | 91 | #endif //__EDITWIDGET_H__ 92 | -------------------------------------------------------------------------------- /src/lawn/widget/NewUserDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "NewUserDialog.h" 2 | #include "LawnApp.h" 3 | #include "Resources.h" 4 | #include "lawn/LawnCommon.h" 5 | #include "widget/WidgetManager.h" 6 | 7 | // 0x45D610 8 | // GOTY @Patoke: 0x460F20 9 | NewUserDialog::NewUserDialog(LawnApp *theApp, const bool isRename) 10 | : LawnDialog( 11 | theApp, isRename ? Dialogs::DIALOG_RENAMEUSER : Dialogs::DIALOG_CREATEUSER, true, 12 | // @Patoke: these locals don't exist 13 | isRename ? _S("RENAME USER") : _S("NEW USER"), _S("Please enter your name:"), _S("[DIALOG_BUTTON_OK]"), 14 | Dialog::BUTTONS_OK_CANCEL 15 | ) { 16 | mApp = theApp; 17 | mVerticalCenterText = false; 18 | mNameEditWidget = CreateEditWidget(0, this, this); 19 | mNameEditWidget->mMaxChars = 12; 20 | mNameEditWidget->AddWidthCheckFont(FONT_BRIANNETOD16, 220); 21 | CalcSize(110, 40); 22 | } 23 | 24 | // 0x45D7E0、0x45D800 25 | NewUserDialog::~NewUserDialog() { delete mNameEditWidget; } 26 | 27 | // 0x45D870 28 | void NewUserDialog::AddedToManager(WidgetManager *theWidgetManager) { 29 | LawnDialog::AddedToManager(theWidgetManager); 30 | AddWidget(mNameEditWidget); 31 | theWidgetManager->SetFocus(mNameEditWidget); 32 | } 33 | 34 | // 0x45D8E0 35 | void NewUserDialog::RemovedFromManager(WidgetManager *theWidgetManager) { 36 | LawnDialog::RemovedFromManager(theWidgetManager); 37 | RemoveWidget(mNameEditWidget); 38 | } 39 | 40 | int NewUserDialog::GetPreferredHeight(const int theWidth) { return LawnDialog::GetPreferredHeight(theWidth) + 40; } 41 | 42 | // 0x45D910 43 | void NewUserDialog::Resize(const int theX, const int theY, const int theWidth, const int theHeight) { 44 | LawnDialog::Resize(theX, theY, theWidth, theHeight); 45 | mNameEditWidget->Resize( 46 | mContentInsets.mLeft + 12, mHeight - 155, mWidth - mContentInsets.mLeft - mContentInsets.mRight - 24, 28 47 | ); 48 | } 49 | 50 | // 0x45D970 51 | void NewUserDialog::Draw(Graphics *g) { 52 | LawnDialog::Draw(g); 53 | DrawEditBox(g, mNameEditWidget); 54 | } 55 | 56 | // 0x45D9D0 57 | void NewUserDialog::EditWidgetText(const int theId, const SexyString &theString) { 58 | (void)theId; 59 | (void)theString; 60 | mApp->ButtonDepress(mId + 2000); 61 | } 62 | 63 | // 0x45D9F0 64 | bool NewUserDialog::AllowChar(int, const SexyChar theChar) { return isalnum(theChar) || theChar == _S(' '); } 65 | 66 | // 0x45DA20 67 | SexyString NewUserDialog::GetName() const { 68 | SexyString aString; 69 | SexyChar aLastChar = _S(' '); 70 | 71 | for (size_t i = 0; i < mNameEditWidget->mString.size(); i++) { 72 | const SexyChar aChar = mNameEditWidget->mString[i]; 73 | if (aChar != _S(' ')) { 74 | aString.append(1, aChar); 75 | } else if (aChar != aLastChar) { 76 | aString.append(1, _S(' ')); 77 | } 78 | 79 | aLastChar = aChar; 80 | } 81 | 82 | if (aString.size() && aString[aString.size() - 1] == _S(' ')) { 83 | aString.resize(aString.size() - 1); 84 | } 85 | 86 | return aString; 87 | } 88 | 89 | void NewUserDialog::SetName(const SexyString &theName) const { 90 | mNameEditWidget->SetText(theName, true); 91 | mNameEditWidget->mCursorPos = theName.size(); 92 | mNameEditWidget->mHilitePos = 0; 93 | } 94 | -------------------------------------------------------------------------------- /src/todlib/TodList.cpp: -------------------------------------------------------------------------------- 1 | #include "TodList.h" 2 | #include "TodCommon.h" 3 | #include "TodDebug.h" 4 | #include "misc/Debug.h" 5 | 6 | void TodAllocator::Initialize(int theGrowCount, int theItemSize) { 7 | TOD_ASSERT(static_cast(theItemSize) >= sizeof(void *)); 8 | 9 | mFreeList = nullptr; 10 | mBlockList = nullptr; 11 | mGrowCount = theGrowCount; 12 | mTotalItems = 0; 13 | mItemSize = theItemSize; 14 | } 15 | 16 | void TodAllocator::Dispose() { FreeAll(); } 17 | 18 | // 0x4438C0 19 | void TodAllocator::Grow() { 20 | TOD_ASSERT(mGrowCount > 0); 21 | TOD_ASSERT(static_cast(mItemSize) >= sizeof(void *)); 22 | 23 | void *aBlock = TodMalloc(mGrowCount * mItemSize + sizeof(void *)); 24 | *static_cast(aBlock) = mBlockList; 25 | mBlockList = aBlock; 26 | 27 | void *aFreeList = mFreeList; 28 | auto aItem = reinterpret_cast(reinterpret_cast(aBlock) + sizeof(void *)); 29 | for (int i = 0; i < mGrowCount; i++) { 30 | *static_cast(aItem) = aFreeList; 31 | aFreeList = aItem; 32 | aItem = reinterpret_cast(reinterpret_cast(aItem) + mItemSize); 33 | } 34 | mFreeList = aFreeList; 35 | } 36 | 37 | bool TodAllocator::IsPointerFromAllocator(void *theItem) const { 38 | const size_t aBlockSize = mGrowCount * mItemSize; // 每次“Grow”的内存大小,即每个区块的内存大小 39 | for (void *aPtr = mBlockList; aPtr != nullptr; aPtr = *static_cast(aPtr)) { 40 | const uintptr_t aItemPtr = reinterpret_cast(theItem); 41 | // 区块的首个四字节为额外申请的、用于存储指向下一区块的指针的区域 42 | const uintptr_t aBlockPtr = reinterpret_cast(aPtr) + sizeof(void *); 43 | // 判断 theItem 是否位于当前区块内且指向某一项的区域的起始地址 44 | if (aItemPtr >= aBlockPtr && aItemPtr < aBlockPtr + aBlockSize && (aItemPtr - aBlockPtr) % mItemSize == 0) 45 | return true; 46 | } 47 | return false; 48 | } 49 | 50 | bool TodAllocator::IsPointerOnFreeList(const void *theItem) const { 51 | for (void *aPtr = mFreeList; aPtr != nullptr; aPtr = *static_cast(aPtr)) 52 | if (theItem == aPtr) return true; 53 | return false; 54 | } 55 | 56 | void *TodAllocator::Alloc(int theItemSize) { 57 | (void)theItemSize; 58 | mTotalItems++; 59 | if (mFreeList == nullptr) Grow(); 60 | 61 | const auto anItem = (void *)mFreeList; 62 | mFreeList = *static_cast(anItem); 63 | return anItem; 64 | } 65 | 66 | void *TodAllocator::Calloc(int theItemSize) { 67 | void *anItem = Alloc(theItemSize); 68 | memset(anItem, 0, theItemSize); 69 | return anItem; 70 | } 71 | 72 | void TodAllocator::Free(void *theItem, int theItemSize) { 73 | (void)theItemSize; 74 | mTotalItems--; 75 | TOD_ASSERT(IsPointerFromAllocator(theItem)); 76 | TOD_ASSERT(!IsPointerOnFreeList(theItem)); 77 | *static_cast(theItem) = mFreeList; // 将原可用区域头存入 [*theItem] 中 78 | mFreeList = theItem; // 将 theItem 设为新的可用区域头 79 | } 80 | 81 | void TodAllocator::FreeAll() { 82 | for (void *aBlock = mBlockList; aBlock != nullptr;) { 83 | void *aNext = *static_cast(aBlock); 84 | TodFree(aBlock); 85 | aBlock = aNext; 86 | } 87 | 88 | mBlockList = nullptr; 89 | mFreeList = nullptr; 90 | mTotalItems = 0; 91 | } 92 | -------------------------------------------------------------------------------- /src/lawn/widget/ChallengeScreen.h: -------------------------------------------------------------------------------- 1 | #ifndef __CHALLENGESCREEN_H__ 2 | #define __CHALLENGESCREEN_H__ 3 | 4 | #include "ConstEnums.h" 5 | #include "framework/widget/Dialog.h" 6 | using namespace Sexy; 7 | 8 | #define NUM_CHALLENGE_MODES ((int)GameMode::NUM_GAME_MODES - 1) 9 | 10 | class LawnApp; 11 | class ToolTipWidget; 12 | class NewLawnButton; 13 | 14 | class ChallengeScreen : public Widget, public ButtonListener { 15 | private: 16 | enum { ChallengeScreen_Back = 100, ChallengeScreen_Mode = 200, ChallengeScreen_Page = 300 }; 17 | 18 | public: 19 | NewLawnButton *mBackButton; //+0x8C 20 | ButtonWidget *mPageButton[static_cast(ChallengePage::MAX_CHALLANGE_PAGES)]; //+0x90 21 | ButtonWidget *mChallengeButtons[NUM_CHALLENGE_MODES]; //+0xA0 22 | LawnApp *mApp; //+0x1C0 23 | ToolTipWidget *mToolTip; //+0x1C4 24 | ChallengePage mPageIndex; //+0x1C8 25 | bool mCheatEnableChallenges; //+0x1CC 26 | UnlockingState mUnlockState; //+0x1D0 27 | int mUnlockStateCounter; //+0x1D4 28 | int mUnlockChallengeIndex; //+0x1D8 29 | float mLockShakeX; //+0x1DC 30 | float mLockShakeY; //+0x1E0 31 | 32 | public: 33 | ChallengeScreen(LawnApp *theApp, ChallengePage thePage); 34 | ~ChallengeScreen() override; 35 | void SetUnlockChallengeIndex(ChallengePage thePage, bool theIsIZombie = false); 36 | int MoreTrophiesNeeded(int theChallengeIndex); 37 | /*inline*/ bool ShowPageButtons() const; 38 | void UpdateButtons() const; 39 | int AccomplishmentsNeeded(int theChallengeIndex); 40 | void DrawButton(Graphics *g, int theChallengeIndex); 41 | void Draw(Graphics *g) override; 42 | void Update() override; 43 | void AddedToManager(WidgetManager *theWidgetManager) override; 44 | void RemovedFromManager(WidgetManager *theWidgetManager) override; 45 | void ButtonPress(int theId) override; 46 | 47 | void ButtonDownTick(int) override {} 48 | 49 | void ButtonMouseEnter(int) override {} 50 | 51 | void ButtonMouseLeave(int) override {} 52 | 53 | void ButtonMouseMove(int, int, int) override {} 54 | 55 | void ButtonDepress(int theId) override; 56 | void UpdateToolTip(); 57 | // virtual void KeyChar(char theChar); 58 | 59 | /*inline*/ static bool IsScaryPotterLevel(GameMode theGameMode); 60 | /*inline*/ static bool IsIZombieLevel(GameMode theGameMode); 61 | }; 62 | 63 | class ChallengeDefinition { 64 | public: 65 | GameMode mChallengeMode; 66 | int mChallengeIconIndex; 67 | ChallengePage mPage; 68 | int mRow; 69 | int mCol; 70 | const SexyChar *mChallengeName; 71 | }; 72 | 73 | extern ChallengeDefinition gChallengeDefs[NUM_CHALLENGE_MODES]; 74 | 75 | ChallengeDefinition &GetChallengeDefinition(int theChallengeMode); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/framework/misc/KeyCodes.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEYCODES_INCLUDED__ 2 | #define __KEYCODES_INCLUDED__ 3 | #include 4 | 5 | namespace Sexy { 6 | // Don't need typedef 7 | /*typedef*/ 8 | enum KeyCode : uint8_t { 9 | KEYCODE_UNKNOWN = 0x00, 10 | KEYCODE_LBUTTON = 0x01, 11 | KEYCODE_RBUTTON = 0x02, 12 | KEYCODE_CANCEL = 0x03, 13 | KEYCODE_MBUTTON = 0x04, 14 | KEYCODE_BACK = 0x08, 15 | KEYCODE_TAB = 0x09, 16 | KEYCODE_CLEAR = 0x0C, 17 | KEYCODE_RETURN = 0x0D, 18 | KEYCODE_SHIFT = 0x10, 19 | KEYCODE_CONTROL = 0x11, 20 | KEYCODE_MENU = 0x12, 21 | KEYCODE_PAUSE = 0x13, 22 | KEYCODE_CAPITAL = 0x14, 23 | KEYCODE_KANA = 0x15, 24 | KEYCODE_HANGEUL = 0x15, 25 | KEYCODE_HANGUL = 0x15, 26 | KEYCODE_JUNJA = 0x17, 27 | KEYCODE_FINAL = 0x18, 28 | KEYCODE_HANJA = 0x19, 29 | KEYCODE_KANJI = 0x19, 30 | KEYCODE_ESCAPE = 0x1B, 31 | KEYCODE_CONVERT = 0x1C, 32 | KEYCODE_NONCONVERT = 0x1D, 33 | KEYCODE_ACCEPT = 0x1E, 34 | KEYCODE_MODECHANGE = 0x1F, 35 | KEYCODE_SPACE = 0x20, 36 | KEYCODE_PRIOR = 0x21, 37 | KEYCODE_NEXT = 0x22, 38 | KEYCODE_END = 0x23, 39 | KEYCODE_HOME = 0x24, 40 | KEYCODE_LEFT = 0x25, 41 | KEYCODE_UP = 0x26, 42 | KEYCODE_RIGHT = 0x27, 43 | KEYCODE_DOWN = 0x28, 44 | KEYCODE_SELECT = 0x29, 45 | KEYCODE_PRINT = 0x2A, 46 | KEYCODE_EXECUTE = 0x2B, 47 | KEYCODE_SNAPSHOT = 0x2C, 48 | KEYCODE_INSERT = 0x2D, 49 | KEYCODE_DELETE = 0x2E, 50 | KEYCODE_HELP = 0x2F, 51 | KEYCODE_ASCIIBEGIN = 0x30, 52 | KEYCODE_ASCIIEND = 0x5A, 53 | KEYCODE_LWIN = 0x5B, 54 | KEYCODE_RWIN = 0x5C, 55 | KEYCODE_APPS = 0x5D, 56 | KEYCODE_NUMPAD0 = 0x60, 57 | KEYCODE_NUMPAD1 = 0x61, 58 | KEYCODE_NUMPAD2 = 0x62, 59 | KEYCODE_NUMPAD3 = 0x63, 60 | KEYCODE_NUMPAD4 = 0x64, 61 | KEYCODE_NUMPAD5 = 0x65, 62 | KEYCODE_NUMPAD6 = 0x66, 63 | KEYCODE_NUMPAD7 = 0x67, 64 | KEYCODE_NUMPAD8 = 0x68, 65 | KEYCODE_NUMPAD9 = 0x69, 66 | KEYCODE_MULTIPLY = 0x6A, 67 | KEYCODE_ADD = 0x6B, 68 | KEYCODE_SEPARATOR = 0x6C, 69 | KEYCODE_SUBTRACT = 0x6D, 70 | KEYCODE_DECIMAL = 0x6E, 71 | KEYCODE_DIVIDE = 0x6F, 72 | KEYCODE_F1 = 0x70, 73 | KEYCODE_F2 = 0x71, 74 | KEYCODE_F3 = 0x72, 75 | KEYCODE_F4 = 0x73, 76 | KEYCODE_F5 = 0x74, 77 | KEYCODE_F6 = 0x75, 78 | KEYCODE_F7 = 0x76, 79 | KEYCODE_F8 = 0x77, 80 | KEYCODE_F9 = 0x78, 81 | KEYCODE_F10 = 0x79, 82 | KEYCODE_F11 = 0x7A, 83 | KEYCODE_F12 = 0x7B, 84 | KEYCODE_F13 = 0x7C, 85 | KEYCODE_F14 = 0x7D, 86 | KEYCODE_F15 = 0x7E, 87 | KEYCODE_F16 = 0x7F, 88 | KEYCODE_F17 = 0x80, 89 | KEYCODE_F18 = 0x81, 90 | KEYCODE_F19 = 0x82, 91 | KEYCODE_F20 = 0x83, 92 | KEYCODE_F21 = 0x84, 93 | KEYCODE_F22 = 0x85, 94 | KEYCODE_F23 = 0x86, 95 | KEYCODE_F24 = 0x87, 96 | KEYCODE_NUMLOCK = 0x90, 97 | KEYCODE_SCROLL = 0x91, 98 | KEYCODE_LSHIFT = 0xA0, 99 | KEYCODE_RSHIFT = 0xA1, 100 | KEYCODE_LCONTROL = 0xA2, 101 | KEYCODE_RCONTROL = 0xA3, 102 | KEYCODE_LMENU = 0xA4, 103 | KEYCODE_RMENU = 0xA5, 104 | KEYCODE_ASCIIBEGIN2 = 0xB3, 105 | // ASCII + 0x80 106 | KEYCODE_ASCIIEND2 = 0xE0 107 | }; 108 | 109 | KeyCode GetKeyCodeFromName(const std::string &theKeyName); 110 | std::string GetKeyNameFromCode(const KeyCode &theKeyCode); 111 | } // namespace Sexy 112 | 113 | #endif //__KEYCODES_INCLUDED__ 114 | --------------------------------------------------------------------------------