├── .gitignore ├── README.md ├── build.py ├── check.py ├── data ├── funcSizes.txt ├── functions.csv ├── genSizes.py ├── main.map └── percent.json ├── docs └── CONTRIBUTING.md ├── include ├── Game │ ├── System │ │ ├── AtmosTypeFunction.h │ │ ├── BadgeConditionType.h │ │ ├── CourseCollectItemInfo.h │ │ ├── PlayerSelectType.h │ │ ├── StageDatabaseInfo.h │ │ ├── StageType.h │ │ ├── StageUserData.h │ │ └── StampType.h │ ├── Util.h │ ├── Util │ │ └── PlayerUtil.h │ └── al │ │ ├── Interfaces.h │ │ ├── LiveActor │ │ ├── HitSensor.h │ │ ├── LiveActor.h │ │ ├── LiveActorFlag.h │ │ ├── NerveExecutor.h │ │ ├── NerveKeeper.h │ │ ├── NerveStateBase.h │ │ ├── NerveUtil.h │ │ └── SensorHitGroup.h │ │ ├── Util.h │ │ └── Util │ │ └── StringUtil.h ├── sead.h └── sead │ ├── seadMatrix.h │ ├── seadSafeString.h │ └── seadVector.h ├── nso.py ├── progress.py ├── setup.py └── source └── Game ├── System ├── AtmosTypeFunction.cpp ├── BadgeConditionType.cpp ├── CourseCollectItemInfo.cpp ├── PlayerSelectType.cpp ├── StageDatabaseInfo.cpp ├── StageType.cpp ├── StageUserData.cpp └── StampType.cpp ├── Util └── PlayerUtil.cpp └── al ├── LiveActor ├── HitSensor.cpp ├── LiveActor.cpp ├── NerveExecutor.cpp ├── NerveUtil.cpp └── SensorHitGroup.cpp └── Util └── StringUtil.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | .vscode 3 | .editorconfig 4 | tools/*.exe 5 | tools/*.dll 6 | deps 7 | *.idb 8 | *.id0 9 | *.id1 10 | *.id2 11 | *.nam 12 | *.til 13 | *.o 14 | *.out 15 | *.elf 16 | *.dol 17 | *.a 18 | *.d 19 | build 20 | __pycache__ 21 | .ninja_log 22 | .ninja_deps 23 | build.ninja 24 | map/* 25 | *.nso -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cttt-decomp 2 | A decompilation of the Nintendo Switch version of Captain Toad: Treasure Tracker [v1.3.0]. 3 | 4 | 5 | 6 | chat on our Discord 8 | 9 | ## Build Instructions 10 | 11 | 1. Obtain a clean copy of a `main` from Captain Toad: Treasure Tracker v1.3.0 and rename it to `cttt.nso`, and place it on the root. 12 | 2. Run `setup.py` to download and install all of the dependencies. These dependencies are `capstone`, `elftools`, `lz4`, `ninja`, and `colorama`. It will also download a zipped file that contains the compiler and other headers for easy use of the NNSDK. 13 | 3. Run `build.py`, then use `check.py` to verify matching status. For more information, see docs/Contributing. 14 | 15 | ## Contributions 16 | 17 | Want to contribute, or learn how to contribute? Try joining our Discord server (link is at the top), and looking into docs/Contributing! We will be glad to answer any questions for people who wish to contribute. All pull requests and issues are welcome. -------------------------------------------------------------------------------- /build.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | import pathlib 5 | import shutil 6 | 7 | COMPILER_CMD = "-x c++ -std=gnu++14 -fno-common -fno-strict-aliasing -fno-short-enums -fdata-sections -fPIC -mcpu=cortex-a57+fp+simd+crypto+crc -O3 -fno-slp-vectorize -fno-exceptions -fomit-frame-pointer -Wall -I deps/Include -I deps/Common/Configs/Targets/NX-NXFP2-a64/Include -I include -DNN_NINTENDO_SDK -DNN_SDK_BUILD_RELEASE -c " 8 | COMPILER_PATH = pathlib.Path("deps/Compilers/NX/nx/aarch64/bin/clang++.exe") 9 | OBJDUMP_PATH = pathlib.Path("deps/Compilers/NX/nx/aarch64/bin/aarch64-nintendo-nx-elf-objdump.exe") 10 | 11 | # todo -- implement ninja 12 | tasks = list() 13 | 14 | for root, dirs, files in os.walk("source"): 15 | for file in files: 16 | if file.endswith(".cpp"): 17 | source_path = os.path.join(root, file) 18 | build_path = source_path.replace("source", "build", 1).replace(".cpp", ".o") 19 | map_path = build_path.replace("build", "map", 1).replace(".o", ".map") 20 | 21 | os.makedirs(os.path.dirname(build_path), exist_ok=True) 22 | os.makedirs(os.path.dirname(map_path), exist_ok=True) 23 | tasks.append((source_path, build_path, map_path)) 24 | 25 | for task in tasks: 26 | source_path, build_path, map_path = task 27 | 28 | print(f"Compiling {source_path}...") 29 | if subprocess.call(f"{COMPILER_PATH} {COMPILER_CMD} {source_path} -o {build_path}", shell=True) == 1: 30 | sys.exit(1) 31 | 32 | mapFileOutput = subprocess.check_output([OBJDUMP_PATH, build_path, "-t"]).decode("utf-8").replace("\r", "") 33 | lines = mapFileOutput.split("\n") 34 | 35 | newOutput = [] 36 | 37 | for line in lines: 38 | if line == '': 39 | continue 40 | 41 | if line.startswith("build") or line.startswith("SYMBOL TABLE"): 42 | continue 43 | 44 | more_split = line.split(" ") 45 | 46 | # if global, it is most likely a symbol 47 | if more_split[1] == "g": 48 | # symbol is always the last entry 49 | sym = more_split[(len(more_split) - 1)] 50 | newOutput.append(f"{sym}\n") 51 | 52 | 53 | with open(map_path, "w") as w: 54 | w.writelines(newOutput) 55 | -------------------------------------------------------------------------------- /check.py: -------------------------------------------------------------------------------- 1 | import glob, nso, os, sys 2 | from colorama import Fore, Style 3 | from capstone import * 4 | from elftools.elf.elffile import ELFFile 5 | 6 | def getModule(sym): 7 | for root, dirs, files in os.walk("map"): 8 | for file in files: 9 | if file.endswith(".map"): 10 | map_path = os.path.join(root, file) 11 | with open(map_path, "r") as f: 12 | lines = f.readlines() 13 | 14 | 15 | for line in lines: 16 | fmt = line.replace("\n", "") 17 | if fmt == sym: 18 | # we found where our symbol lives! 19 | # we just grab the source module 20 | object_path = map_path.replace("map", "build", 1) 21 | object_path = object_path.replace(".map", ".o") 22 | return object_path 23 | return "" 24 | 25 | if len(sys.argv) < 2: 26 | print("python check.py [-no-diff] symbol_name") 27 | sys.exit(1) 28 | 29 | 30 | printDiff = True 31 | 32 | if "-no-diff" in sys.argv: 33 | sym = sys.argv[2] 34 | printDiff = Fals 35 | else: 36 | sym = sys.argv[1] 37 | 38 | func_sizes = { } 39 | sym_map = { } 40 | 41 | with open("data/funcSizes.txt", "r") as f: 42 | lines = f.readlines() 43 | 44 | for line in lines: 45 | spl = line.split("=") 46 | func_sizes[spl[0]] = spl[1].replace("\n", "") 47 | 48 | with open("data/main.map", "r") as f: 49 | lines = f.readlines() 50 | 51 | for line in lines: 52 | spl = line.split("=") 53 | addr = spl[0] 54 | addr = addr[10:] 55 | name = spl[1].replace("\n", "") 56 | sym_map[name] = int(addr, 16) 57 | 58 | if sym not in sym_map: 59 | print("Symbol not found.") 60 | sys.exit(1) 61 | 62 | with open("cttt.nso", "rb") as f: 63 | nso_file = nso.NSO(f.read()) 64 | 65 | funcData = nso_file.getFunction(sym_map[sym], int(func_sizes[sym])) 66 | capstone_inst = Cs(CS_ARCH_ARM64, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN) 67 | capstone_inst.detail = True 68 | capstone_inst.imm_unsigned = False 69 | 70 | error_count = 0 71 | warning_count = 0 72 | 73 | original_instrs = list(capstone_inst.disasm(funcData, 0)) 74 | 75 | object_path = getModule(sym) 76 | if object_path == "": 77 | print("Failed to find object.") 78 | sys.exit(1) 79 | 80 | with open(object_path, "rb") as f: 81 | elf = f 82 | 83 | elf_file = ELFFile(elf) 84 | symtab = elf_file.get_section_by_name('.symtab') 85 | 86 | if symtab.get_symbol_by_name(sym) is None: 87 | print("Could not find symbol in object file. This may be caused by the code not being compiled, the function being in the wrong C++ source file or the function signature being wrong.") 88 | sys.exit(1) 89 | 90 | compiled_symbol = symtab.get_symbol_by_name(sym)[0] 91 | custom_offset = compiled_symbol["st_value"] 92 | custom_size = compiled_symbol['st_size'] 93 | text = elf_file.get_section_by_name('.text') 94 | custom_data = text.data()[custom_offset:custom_offset + custom_size] 95 | custom_instructions = list(capstone_inst.disasm(custom_data, 0)) 96 | 97 | orig_length = len(list(original_instrs)) 98 | cust_length = len(list(custom_instructions)) 99 | 100 | if orig_length != cust_length: 101 | print("Custom function does not match the size of the original.") 102 | sys.exit(1) 103 | 104 | instr_equal = True 105 | regs_equal = True 106 | 107 | for i in range(orig_length): 108 | curOrigInstr = original_instrs[i] 109 | curCustInstr = custom_instructions[i] 110 | 111 | orig_operands = curOrigInstr.operands 112 | cust_operands = curCustInstr.operands 113 | 114 | if str(curOrigInstr) == str(curCustInstr): 115 | if printDiff == True: 116 | print(f"{Fore.GREEN}{str(curOrigInstr):<80}{curCustInstr}{Style.RESET_ALL}") 117 | continue 118 | 119 | if curOrigInstr.id != curCustInstr.id: 120 | print(f"{Fore.RED}{str(curOrigInstr):<80}{curCustInstr}{Style.RESET_ALL}") 121 | instr_equal = False 122 | continue 123 | 124 | for j in range(len(orig_operands)): 125 | if orig_operands[j].reg != cust_operands[j]: 126 | # ADRP and ADD can give of wrong operands because of us not linking, same with LDR 127 | if curOrigInstr.id == 9 or curOrigInstr.id == 6 or curOrigInstr.id == 162: 128 | print(f"{Fore.YELLOW}{str(curOrigInstr):<80}{curCustInstr}{Style.RESET_ALL}") 129 | # B and BL instructions 130 | elif curOrigInstr.id == 21 or curOrigInstr.id == 16: 131 | print(f"{Fore.YELLOW}{str(curOrigInstr):<80}{curCustInstr}{Style.RESET_ALL}") 132 | else: 133 | print(f"{Fore.RED}{str(curOrigInstr):<80}{curCustInstr}{Style.RESET_ALL}") 134 | regs_equal = False 135 | break 136 | 137 | isAlreadyMarked = False 138 | 139 | if instr_equal == True and regs_equal == True: 140 | 141 | with open("data/functions.csv", "r") as f: 142 | csvData = f.readlines() 143 | 144 | outCsv = [] 145 | 146 | for c in csvData: 147 | spl = c.split(",") 148 | 149 | if spl[1] == sym and spl[2] == "false\n": 150 | outCsv.append(f"{spl[0]},{spl[1]},true\n") 151 | elif spl[1] == sym and spl[2] == "true\n": 152 | isAlreadyMarked = True 153 | outCsv.append(c) 154 | else: 155 | outCsv.append(c) 156 | 157 | with open("data/functions.csv", "w") as w: 158 | w.writelines(outCsv) 159 | 160 | if isAlreadyMarked == True: 161 | print("Function is already marked as decompiled.") 162 | else: 163 | print("Function is matching! Marking as decompiled...") 164 | 165 | elif instr_equal == True and regs_equal == False: 166 | print("Function has matching instructions, but operands are not equal.") 167 | elif instr_equal == False and regs_equal == True: 168 | print("Function has matching operands, but instructions are not equal.") 169 | elif instr_equal == False and regs_equal == False: 170 | print("Function does not match in either instructions or operands.") -------------------------------------------------------------------------------- /data/genSizes.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | 3 | LAST_FUNC_END = 0x6BEF28 4 | 5 | with open("main.map", "r") as f: 6 | lines = f.readlines() 7 | 8 | output = [] 9 | 10 | for i in range(len(lines)): 11 | line_split = lines[i].split("=") 12 | func_name = line_split[1].replace("\n", "") 13 | func_addr = line_split[0] 14 | # remove 0000007100 15 | func_addr = func_addr[10:] 16 | 17 | next_func_addr = 0 18 | if i == len(lines) - 1: 19 | next_func_addr = LAST_FUNC_END 20 | else: 21 | next_addr = lines[i + 1].split("=")[0] 22 | next_addr = next_addr[10:] 23 | next_func_addr = int(next_addr, 16) 24 | 25 | func_size = next_func_addr - int(func_addr, 16) 26 | output.append(f"{func_name}={func_size}\n") 27 | 28 | with open("funcSizes.txt", "w") as w: 29 | w.writelines(output) -------------------------------------------------------------------------------- /data/percent.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "label": "decompiled", 4 | "message": "0.09047818853618732%", 5 | "color": "blue" 6 | } -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | To contribute, you will need the following tools: 4 | 5 | * A disassembler, IDA Pro or Ghidra work very well (you can also use a decompiler, it can make some things easier) 6 | * Python 3.7 and higher 7 | 8 | It is recommended that you have knowledge of the following: 9 | 10 | * C / C++ (however, C++ is STRONGLY recommended) 11 | * Aarch64 Assembly 12 | * Reverse engineering instructions from PowerPC to C / C++ 13 | 14 | Decompilers such as Hex-Rays (included in IDA Pro) are useful as they can make the decompilation easier to write. 15 | 16 | Be sure that all of your submitted code follows the guidelines that are listed below. It is REQUIRED that the output is 1:1. After the code matches, be sure to run `check.py` to check the function that you want to mark. If it matches, it will automatically be marked as decompiled. 17 | 18 | If you have any questions or concerns, please join [our Discord server](https://discord.gg/x7qhJKU3QN)! 19 | 20 | ## Guidelines 21 | 22 | ### General 23 | 24 | * Lines should not exceed 100 characters, these can be split into multiple lines 25 | * Use `nullptr` when assigning or comparing a pointer, not `0` -- Only use `0` when assigning or comparing a value 26 | 27 | ### Headers 28 | 29 | * Use `#pragma once` at the top of each header file 30 | * Use forward-declared types when possible 31 | 32 | 33 | ### Includes 34 | 35 | * Use `#include<>` for system library includes 36 | * Use `#include "..."` for including game headers, and they must be relative to `include` 37 | 38 | ### Names 39 | 40 | * Names for known symbols should match exactly, even including typoes in the symbol 41 | * Member variables must be prefixed with `m` 42 | * Arguments for functions must be prefixed with `p` for pointers or `r` for passed-by-reference 43 | * Static variables with no known symbol must be prefixed with `s`, with globals prefixed with `g` 44 | * Functions with no symbols (such as inlined functions), must use camelCase 45 | 46 | ### Classes 47 | 48 | * Functions for classes must be put in this order: constructor, destructor, operators, virtual functions, member functions 49 | * If the virtual functions are not in the order that they are in the vtable, then the rule above can be ignored as these functions must be placed in order 50 | * When referencing a class member, do not use `this->`, unless it is required for compilation 51 | 52 | 53 | ### Nonmatching Code 54 | If your code does NOT match, use the `NONMATCHING` macro, and explain in a comment why it does not match. 55 | -------------------------------------------------------------------------------- /include/Game/System/AtmosTypeFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define ATMOS_TYPE_UNUSE 0 4 | #define ATMOS_TYPE_SCATTER 1 5 | #define ATMOS_TYPE_AGL_LIGHT_SCATTER 2 6 | 7 | class AtmosTypeFunction { 8 | public: 9 | static int calcAtmosTypeID(const char *pType); 10 | static bool isUnuse(const char *pType); 11 | static bool isUseAtmosScatter(const char *pType); 12 | static bool isUseAglLightScatter(const char *pType); 13 | }; -------------------------------------------------------------------------------- /include/Game/System/BadgeConditionType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BADGE_CONDITION_TYPE_INVALID 0 4 | #define BADGE_CONDITION_TYPE_COIN_NUM 1 5 | #define BADGE_CONDITION_TYPE_TOUCH_NUM 2 6 | #define BADGE_CONDITION_TYPE_ON_SWITCH_CHECKER 3 7 | #define BADGE_CONDITION_TYPE_OFF_SWITCH_CHECKER 4 8 | #define BADGE_CONDITION_TYPE_GET_KINOKO_ONE_UP 5 9 | #define BADGE_CONDITION_TYPE_RADISH_THROW_NUM 6 10 | #define BADGE_CONDITION_TYPE_NO_DAMAGE 7 11 | #define BADGE_CONDITION_TYPE_SWITCH_BLOCK_NUM 8 12 | #define BADGE_CONDITION_TYPE_DOUBLE_CHERRY_NUM 9 13 | #define BADGE_CONDITION_TYPE_GET_KINOKO_TREASURE 10 14 | #define BADGE_CONDITION_TYPE_NO_FOUND_HEYHO 11 15 | #define BADGE_CONDITION_TYPE_NO_PRESSED_RUN 12 16 | #define BADGE_CONDITION_TYPE_POSTER_TOUCH_NUM 13 17 | #define BADGE_CONDITION_TYPE_DOUBLE_BOSS_BIRD_CLONE_HIT_NUM 14 18 | #define BADGE_CONDITION_TYPE_TERESA_KILLED_NUM 15 19 | #define BADGE_CONDITION_TYPE_KINOPIO_BRIGADE_LIVING_NUM 16 20 | 21 | class BadgeConditionType { 22 | public: 23 | static int calcBadgeConditionTypeID(const char *pType); 24 | static bool isInvalid(const char *pType); 25 | static bool isCoinNum(const char *pType); 26 | static bool isTouchNum(const char *pType); 27 | static bool isOnSwitchChecker(const char *pType); 28 | static bool isOffSwitchChecker(const char *pType); 29 | static bool isGetKinokoOneUp(const char *pType); 30 | static bool isRadishThrowNum(const char *pType); 31 | static bool isNoDamage(const char *pType); 32 | static bool isSwitchBlockNum(const char *pType); 33 | static bool isDoubleCherryNum(const char *pType); 34 | static bool isGetKinokoTreasure(const char *pType); 35 | static bool isNoFoundHeyho(const char *pType); 36 | static bool isNoPressedRun(const char *pType); 37 | static bool isPosterTouchNum(const char *pType); 38 | static bool isDoubleBossBirdCloneHitNum(const char *pType); 39 | static bool isTeresaKilledNum(const char *pType); 40 | static bool isKinopioBrigadeLivingNum(const char *pType); 41 | }; -------------------------------------------------------------------------------- /include/Game/System/CourseCollectItemInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class CourseCollectItemInfo { 4 | public: 5 | CourseCollectItemInfo(); 6 | 7 | void initialize(); 8 | void copy(const CourseCollectItemInfo &rSrc); 9 | int calcCollectItemAcquireNum(int) const; 10 | bool isCompleteAcquire(int numCollectItem) const; 11 | 12 | int mCollectItemFlags; 13 | }; -------------------------------------------------------------------------------- /include/Game/System/PlayerSelectType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PLAYER_SELECT_TYPE_KINOPIO 0 4 | #define PLAYER_SELECT_TYPE_KINOPICO 1 5 | #define PLAYER_SELECT_TYPE_KINOPIO_AND_KINOPICO 2 6 | 7 | class PlayerSelectType { 8 | public: 9 | static int calcPlayerSelectTypeID(const char *pType); 10 | static bool isKinopio(const char *pType); 11 | static bool isKinopico(const char *pType); 12 | static bool isKinopioAndKinopico(const char *pType); 13 | }; -------------------------------------------------------------------------------- /include/Game/System/StageDatabaseInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class BadgeConditionInfo { 4 | public: 5 | BadgeConditionInfo(); 6 | 7 | void registerInfo(const char *pName, int param); 8 | int getTypeID(int index) const; 9 | int getParam(int indexn) const; 10 | 11 | int mInfoCount; // _0 12 | int* mTypeIDs; // _8 13 | int* mParams; // _10 14 | }; 15 | 16 | class StageDatabaseInfo { 17 | public: 18 | StageDatabaseInfo(); 19 | 20 | void initialize(int seasonId, int stageId, int courseId, int pageId, int collectItemNum, 21 | int collectLockNum, int openPageNum, int challengeTime, int badgeCondition1Param, 22 | char const* pBadgeCondition1, char const* pStageName, char const* pStageType, char const* pPlayer, 23 | char const* pClipping, bool offScreenBubble, bool disableStageEntry, bool showGhostTutorial, 24 | bool isGhostBusterStage); 25 | bool isStageNormal() const; 26 | bool isStageBonus() const; 27 | bool isStageGameOverMiniGame() const; 28 | bool isStageTrickArt() const; 29 | bool isStagePictureDemo() const; 30 | bool isStagePicture() const; 31 | bool isStagePrologue() const; 32 | bool isStageSpecialBonus() const; 33 | bool isStageSpecial() const; 34 | bool isStageSpecial3DWorld() const; 35 | bool isStageSpecialManeck() const; 36 | bool isStageSpecialCherry() const; 37 | bool isStageSpecialPrologue() const; 38 | bool isStageSpecialOther() const; 39 | bool isStageLabyrinth() const; 40 | bool isStageWhite() const; 41 | bool isPlayerKinopio() const; 42 | bool isPlayerKinopico() const; 43 | bool isPlayerKinopioAndKinopico() const; 44 | bool isBadgeInvalid(int index) const; 45 | bool isBadgeCoinNum(int index) const; 46 | bool isBadgeTouchNum(int index) const; 47 | bool isBadgeOnSwitchChecker(int index) const; 48 | bool isBadgeOffSwitchChecker(int index) const; 49 | bool isBadgeGetKinokoOneUp(int index) const; 50 | bool isBadgeRadishThrowNum(int index) const; 51 | bool isBadgeNoDamage(int index) const; 52 | bool isBadgeSwitchBlockNum(int index) const; 53 | bool isBadgeDoubleCherryNum(int index) const; 54 | bool isBadgeGetKinokoTreasure(int index) const; 55 | bool isBadgeNoFoundHeyho(int index) const; 56 | 57 | int mSeasonId = 0; // _0 58 | int mStageId = 0; // _4 59 | int mCourseId = 0; // _8 60 | int mPageId = 0; // _C 61 | int mStageType = 0; // _10 62 | int mPlayerSelectType = 0; // _14 63 | int mCollectItemNum = 0; // _18 64 | int mCollectLockNum = 0; // _1C 65 | int mOpenPageNum = 0; // _20 66 | int mChallengeTime = 0; // _24 67 | const char* mStageName = 0; // _28 68 | BadgeConditionInfo* mBadgeConditionInfo = nullptr; // _30 69 | bool mOffScreenBubble = false; // _38 70 | bool mIsValidClipping = false; // _39 71 | bool mDisableStageEntry = false; // _3A 72 | bool mShowGhostTutorial = false; // _3B 73 | bool mIsGhostBusterStage = false; // _3C 74 | }; -------------------------------------------------------------------------------- /include/Game/System/StageType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define STAGE_TYPE_NORMAL 0 4 | #define STAGE_TYPE_BONUS 1 5 | #define STAGE_TYPE_GAME_OVER_MINI_GAME 2 6 | #define STAGE_TYPE_PICTURE_DEMO 3 7 | #define STAGE_TYPE_PICTURE 4 8 | #define STAGE_TYPE_PROLOGUE 5 9 | #define STAGE_TYPE_SPECIAL_3D_WORLD 6 10 | #define STAGE_TYPE_SPECIAL_MANECK 7 11 | #define STAGE_TYPE_SPECIAL_CHERRY 8 12 | #define STAGE_TYPE_SPECIAL_PROLOGUE 9 13 | #define STAGE_TYPE_SPECIAL_BONUS 10 14 | #define STAGE_TYPE_SPECIAL_OTHER 11 15 | #define STAGE_TYPE_TRICK_ART 12 16 | #define STAGE_TYPE_WHITE 13 17 | #define STAGE_TYPE_LABYRINTH 14 18 | 19 | class StageType { 20 | public: 21 | static int calcStageTypeID(const char *pName); 22 | static bool isNormal(const char *pName); 23 | static bool isBonus(const char *pName); 24 | static bool isGameOverMiniGame(const char *pName); 25 | static bool isPictureDemo(const char *pName); 26 | static bool isPicture(const char *pName); 27 | static bool isPrologue(const char *pName); 28 | static bool isSpecial3DWorld(const char *pName); 29 | static bool isSpecialManeck(const char *pName); 30 | static bool isSpecialCherry(const char *pName); 31 | static bool isSpecialPrologue(const char *pName); 32 | static bool isSpecialBonus(const char *pName); 33 | static bool isSpecialOther(const char *pName); 34 | static bool isTrickArt(const char *pName); 35 | static bool isWhite(const char *pName); 36 | }; -------------------------------------------------------------------------------- /include/Game/System/StageUserData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class StageUserData { 4 | public: 5 | StageUserData(); 6 | 7 | void init(); 8 | void setFigureType(int figureType); 9 | void setAlive(bool alive); 10 | 11 | int mFigureType; // _0 12 | bool mIsAlive; // _4 13 | }; -------------------------------------------------------------------------------- /include/Game/System/StampType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define STAMP_TYPE_COURSE 0 4 | #define STAMP_TYPE_DEFAULT 1 5 | #define STAMP_TYPE_MARIO_COMPLETE 2 6 | #define STAMP_TYPE_LUIGI_COMPLETE 3 7 | #define STAMP_TYPE_PEACH_COMPLETE 4 8 | #define STAMP_TYPE_KINOPIO_COMPLETE 5 9 | #define STAMP_TYPE_ROSETTA_COMPLETE 6 10 | 11 | class StampType { 12 | public: 13 | static int calcStampTypeID(const char *pName); 14 | static bool isCourse(const char *pName); 15 | static bool isDefault(const char *pName); 16 | static bool isMarioComplete(const char *pName); 17 | static bool isLuigiComplete(const char *pName); 18 | static bool isPeachComplete(const char *pName); 19 | static bool isKinopioComplete(const char *pName); 20 | static bool isRosettaComplete(const char *pName); 21 | }; -------------------------------------------------------------------------------- /include/Game/Util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/Util/PlayerUtil.h" 4 | -------------------------------------------------------------------------------- /include/Game/Util/PlayerUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PLAYER_FIGURE_KINOPIO 0 4 | #define PLAYER_FIGURE_KINOPICO 1 5 | 6 | namespace kp { 7 | int getPlayerFigureTypeDefault(); 8 | }; -------------------------------------------------------------------------------- /include/Game/al/Interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace al { 4 | class AreaObjDirector; 5 | class AudioKeeper; 6 | class CameraDirector; 7 | class CollisionDirector; 8 | class EffectKeeper; 9 | class NerveKeeper; 10 | class SceneObjHolder; 11 | class StageSwitchKeeper; 12 | 13 | class IUseHioNode { 14 | public: 15 | // nothing 16 | }; 17 | 18 | class HioNode : public IUseHioNode { 19 | public: 20 | // nothing 21 | }; 22 | 23 | class IUseAudioKeeper { 24 | public: 25 | virtual AudioKeeper* getAudioKeeper() const = 0; 26 | }; 27 | 28 | class IUseNerve { 29 | public: 30 | virtual NerveKeeper* getNerveKeeper() const = 0; 31 | }; 32 | 33 | class IUseEffectKeeper { 34 | public: 35 | virtual EffectKeeper* getEffectKeeper() const = 0; 36 | }; 37 | 38 | class IUseSceneObj { 39 | public: 40 | virtual SceneObjHolder* getSceneObjHolder() const = 0; 41 | }; 42 | 43 | class IUseName { 44 | public: 45 | virtual const char* getName() const = 0; 46 | }; 47 | 48 | class IUseStageSwitch : public virtual IUseName { 49 | public: 50 | virtual StageSwitchKeeper* getStageSwitchKeeper() const = 0; 51 | virtual void initStageSwitchKeeper() = 0; 52 | }; 53 | 54 | class IUseCamera { 55 | public: 56 | virtual CameraDirector* getCameraDirector() const = 0; 57 | }; 58 | 59 | class IUseCollision { 60 | public: 61 | virtual CollisionDirector* getCollisionDirector() const = 0; 62 | }; 63 | 64 | class IUseAreaObj { 65 | public: 66 | virtual AreaObjDirector* getAreaObjDirector() const = 0; 67 | }; 68 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/HitSensor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sead.h" 4 | 5 | namespace al { 6 | class LiveActor; 7 | class SensorHitGroup; 8 | 9 | class HitSensor { 10 | public: 11 | 12 | void setFollowPosPtr(const Vec3f *); 13 | void setFollowMtxPtr(const Matrix34f *); 14 | void validate(); 15 | void invalidate(); 16 | void validateBySystem(); 17 | void invalidateBySystem(); 18 | 19 | void update(); 20 | void addHitSensor(al::HitSensor *); 21 | 22 | al::LiveActor* mHostActor; // _0 23 | unsigned int _8; 24 | float _C; 25 | float _10; 26 | float _14; 27 | float _18; 28 | unsigned short mMaxSensorCount; // _1C 29 | unsigned short mCurSensorCount; // _1E 30 | al::HitSensor** mSensors; // _20 31 | long _28; 32 | SensorHitGroup* mHitGroup; // _30 33 | unsigned char _38; 34 | unsigned char _39; 35 | unsigned char _3A; 36 | unsigned char _3B; 37 | int _3C; 38 | long _40; 39 | const Vec3f* mFollowPos; // _48 40 | const Matrix34f* mFollowMtx; // _50 41 | float _58; 42 | float _5C; 43 | float _60; 44 | }; 45 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/LiveActor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/al/Interfaces.h" 4 | 5 | namespace al { 6 | struct ActorInitInfo { 7 | 8 | }; 9 | 10 | class SwitchAreaDirector; 11 | class HitSensor; 12 | class SensorMsg; 13 | class ScreenPointer; 14 | class ScreenPointTarget; 15 | class ActorPoseKeeperBase; 16 | class ActorExecuteInfo; 17 | class ActorActionKeeper; 18 | class ActorItemKeeper; 19 | class ActorScoreKeeper; 20 | class Collider; 21 | class CollisionParts; 22 | class ModelKeeper; 23 | class HitSensorKeeper; 24 | class ScreenPointKeeper; 25 | class HitReactionKeeper; 26 | class RailKeeper; 27 | class ShadowKeeper; 28 | class ActorPrePassLightKeeper; 29 | class ActorOcclusionKeeper; 30 | class SubActorKeeper; 31 | class ActorSceneInfo; 32 | class LiveActorFlag; 33 | 34 | class LiveActor : public IUseNerve, public IUseEffectKeeper, public IUseAudioKeeper, public IUseStageSwitch, public IUseSceneObj, public IUseAreaObj, public IUseCamera, public IUseCollision { 35 | public: 36 | LiveActor(const char *); 37 | 38 | virtual NerveKeeper* getNerveKeeper() const; 39 | virtual ~LiveActor(); 40 | virtual void init(const ActorInitInfo &); 41 | virtual void initAfterPlacement(); 42 | virtual void registerSwitchAreaDirector(SwitchAreaDirector *); 43 | virtual void reappear(); 44 | virtual void appear(); 45 | virtual void makeActorAppeared(); 46 | virtual void kill(); 47 | virtual void makeActorDead(); 48 | virtual bool isForcedHidden() const; 49 | virtual void movement(); 50 | virtual void calcAnim(); 51 | virtual void draw(); 52 | virtual void startClipped(); 53 | virtual void endClipped(); 54 | virtual void attackSensor(HitSensor *, HitSensor *); 55 | virtual void* getOwnerSensor() const; 56 | virtual bool receiveMsg(SensorMsg const*, HitSensor *, HitSensor *); 57 | virtual bool receiveMsgScreenPoint(const SensorMsg *, ScreenPointer *, ScreenPointTarget *); 58 | 59 | virtual const char* getName() const; 60 | virtual void* getBaseMtx() const; // should be sead mtx 61 | virtual EffectKeeper* getEffectKeeper() const; 62 | virtual AudioKeeper* getAudioKeeper() const; 63 | virtual StageSwitchKeeper* getStageSwitchKeeper() const; 64 | virtual SceneObjHolder* getSceneObjHolder() const; 65 | virtual CollisionDirector* getCollisionDirector() const; 66 | virtual AreaObjDirector* getAreaObjDirector() const; 67 | virtual CameraDirector* getCameraDirector() const; 68 | virtual bool isMovePartDisableStaticTouchEffects() const; 69 | virtual void initStageSwitchKeeper(); 70 | virtual void control(); 71 | virtual void calcAndSetBaseMtx(); 72 | virtual void updateCollider(); 73 | 74 | const char* mName = nullptr; 75 | ActorPoseKeeperBase* mPoseKeeper = nullptr; 76 | ActorExecuteInfo* mExecuteInfo = nullptr; 77 | ActorActionKeeper* mActionKeeper = nullptr; 78 | ActorItemKeeper* mItemKeeper = nullptr; 79 | ActorScoreKeeper* mScoreKeeper = nullptr; 80 | Collider* mCollider = nullptr; 81 | CollisionParts* mCollisionParts = nullptr; 82 | ModelKeeper* mModelKeeper = nullptr; 83 | NerveKeeper* mNerveKeeper = nullptr; 84 | HitSensorKeeper* mHitSensorKeeper = nullptr; 85 | ScreenPointKeeper* mScreenPointKeeper = nullptr; 86 | EffectKeeper* mEffectKeeper = nullptr; 87 | AudioKeeper* mAudioKeeper = nullptr; 88 | HitReactionKeeper* mHitReactionKeeper = nullptr; 89 | StageSwitchKeeper* mStageSwitchKeeper = nullptr; 90 | RailKeeper* mRailKeeper = nullptr; 91 | ShadowKeeper* mShadowKeeper = nullptr; 92 | ActorPrePassLightKeeper* mPrePassLightKeeper = nullptr; 93 | ActorOcclusionKeeper* mOcclusionKeeper = nullptr; 94 | void* _E0 = nullptr; 95 | SubActorKeeper* mSubActorKeeper = nullptr; 96 | void* _F0 = nullptr; 97 | ActorSceneInfo* mSceneInfo = nullptr; 98 | LiveActorFlag* mFlags = nullptr; 99 | }; 100 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/LiveActorFlag.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | namespace al { 3 | class LiveActorFlag { 4 | public: 5 | LiveActorFlag(); 6 | bool mIsDead; // _0 7 | bool _1; 8 | bool _2; 9 | bool _3; 10 | bool mIsOnCalcAnim; // _4 11 | bool mIsModelHidden; // _5 12 | bool mIsNoCollide; // _6 13 | bool _7; 14 | bool mIsValidMatCode; // _8 15 | bool mIsAreaTarget; // _9 16 | bool mIsOnMoveEffAudioColSensor; // _A 17 | bool mIsDying; // _B 18 | }; 19 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/NerveExecutor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/al/Interfaces.h" 4 | #include "Game/al/LiveActor/NerveKeeper.h" 5 | 6 | namespace al { 7 | class NerveExecutor : public al::IUseNerve { 8 | public: 9 | NerveExecutor(const char *); 10 | 11 | virtual NerveKeeper* getNerveKeeper() const { 12 | return mNerveKeeper; 13 | } 14 | 15 | virtual ~NerveExecutor(); 16 | 17 | void initNerve(const al::Nerve *, int); 18 | void updateNerve(); 19 | 20 | NerveKeeper* mNerveKeeper; // _8 21 | }; 22 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/NerveKeeper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace al { 4 | class Nerve; 5 | class NerveActionCtrl; 6 | class NerveStateCtrl; 7 | 8 | class NerveKeeper { 9 | public: 10 | NerveKeeper(void *, const Nerve *, int); 11 | 12 | void update(); 13 | void tryChangeNerve(); 14 | void setNerve(const Nerve *pNerve); 15 | Nerve* getCurrentNerve(); 16 | void initNerveAction(NerveActionCtrl *pActionCtrl); 17 | 18 | NerveStateCtrl* mStateCtrl; // _0 19 | void* _8; 20 | Nerve* mNextNerve; // _10 21 | int mStep; // _18 22 | NerveActionCtrl* _20; 23 | NerveActionCtrl* mActionCtrl; // _28 24 | }; 25 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/NerveStateBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/al/LiveActor/NerveExecutor.h" 4 | 5 | namespace al { 6 | class LiveActor; 7 | 8 | class NerveStateBase : public NerveExecutor { 9 | public: 10 | NerveStateBase(const char *); 11 | 12 | virtual ~NerveStateBase(); 13 | virtual void init(); 14 | virtual void appear(); 15 | virtual void kill(); 16 | virtual void update(); 17 | virtual void control(); 18 | 19 | bool mIsDead; // _10 20 | }; 21 | 22 | class ActorStateBase : public NerveExecutor { 23 | public: 24 | ActorStateBase(const char *, LiveActor *); 25 | 26 | virtual ~ActorStateBase(); 27 | virtual void init(); 28 | virtual void appear(); 29 | virtual void kill(); 30 | virtual void update(); 31 | virtual void control(); 32 | 33 | bool mIsDead; // _10 34 | LiveActor* mHostActor; // _18 35 | }; 36 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/NerveUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/al/LiveActor/NerveExecutor.h" 4 | 5 | namespace al { 6 | void setNerve(IUseNerve *pUseNerve, const Nerve *pNerve); 7 | void setNerveAtStep(IUseNerve *pUseNerve, const Nerve *pNerve, int step); 8 | bool isStep(const IUseNerve *pUseNerve, int step); 9 | bool isNerve(const IUseNerve *pUseNerve, const Nerve *pNerve); 10 | int getNerveStep(const IUseNerve *pUseNerve); 11 | bool isFirstStep(const IUseNerve *pUseNerve); 12 | bool isLessStep(const IUseNerve *pUseNerve, int step); 13 | bool isLessEqualStep(const IUseNerve *pUseNerve, int step); 14 | bool isGreaterStep(const IUseNerve *pUseNerve, int step); 15 | bool isGreaterEqualStep(const IUseNerve *pUseNerve, int step); 16 | bool isIntervalStep(const IUseNerve *pUseNerve, int interval, int startStep); 17 | bool isIntervalOnOffStep(const IUseNerve *pUseNerve, int interval, int startStep); 18 | bool isNewNerveStep(const IUseNerve *pUseNerve); 19 | 20 | // There is much more 21 | }; -------------------------------------------------------------------------------- /include/Game/al/LiveActor/SensorHitGroup.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace al { 4 | class HitSensor; 5 | 6 | class SensorHitGroup { 7 | public: 8 | SensorHitGroup(int, const char *); 9 | 10 | void add(al::HitSensor *); 11 | void remove(al::HitSensor *); 12 | al::HitSensor* getSensor(int) const; 13 | void clear() const; 14 | 15 | int mMaxSensorCount; // _0 16 | int mSensorCount; // _4 17 | al::HitSensor** mSensors; // _8 18 | }; 19 | }; -------------------------------------------------------------------------------- /include/Game/al/Util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Game/al/Util/StringUtil.h" -------------------------------------------------------------------------------- /include/Game/al/Util/StringUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sead.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace al { 11 | const char* getBaseName(const char *); 12 | const char* createStringIfInStack(const char *); 13 | 14 | void extractString(char *, const char *, unsigned int, unsigned int); 15 | 16 | bool tryReplaceString(sead::BufferedSafeStringBase *, const char *, const char *); 17 | bool tryReplaceString(sead::BufferedSafeStringBase *, const char *, const char *, const char *); 18 | 19 | bool isEqualString(const char16_t *, const char16_t *); 20 | bool isEqualSubString(const char *, const char *); 21 | bool isEqualSubString(const SafeString &, const SafeString &); 22 | bool isStartWithString(const char *, const char *); 23 | bool isEndWithString(const char *, const char *); 24 | 25 | int compareStringIgnoreCase(const char *, const char *); 26 | 27 | void copyString(char *, const char *, unsigned int); 28 | 29 | bool isInStack(const void *); 30 | 31 | bool isEqualString(const char *, const char *) NN_NOINLINE; 32 | bool isEqualString(const SafeString &, const SafeString &); 33 | bool isEqualStringCase(const char *, const char *); 34 | bool isEqualStringCase(const SafeString &, const SafeString &); 35 | }; -------------------------------------------------------------------------------- /include/sead.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sead/seadMatrix.h" 4 | #include "sead/seadSafeString.h" 5 | #include "sead/seadVector.h" -------------------------------------------------------------------------------- /include/sead/seadMatrix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sead { 4 | template 5 | class Matrix34 { 6 | public: 7 | T mMatrix[3][4]; // _0 8 | }; 9 | }; 10 | 11 | typedef sead::Matrix34 Matrix34f; -------------------------------------------------------------------------------- /include/sead/seadSafeString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sead { 4 | template 5 | class SafeStringBase { 6 | public: 7 | SafeStringBase() : mString(&cNullChar) { 8 | 9 | } 10 | 11 | virtual ~SafeStringBase() = default; 12 | virtual SafeStringBase& operator=(const SafeStringBase &) = 0; 13 | virtual void assureTerminationImpl_() const { 14 | 15 | } 16 | 17 | inline const T* cstr() const { 18 | assureTerminationImpl_(); 19 | return mString; 20 | } 21 | 22 | const T* mString; // _8 23 | 24 | static const T cNullChar; 25 | static const int cMaximumLength = 0x80000; 26 | }; 27 | 28 | template 29 | class BufferedSafeStringBase : public SafeStringBase { 30 | public: 31 | BufferedSafeStringBase(T *pBuffer, int size) : SafeStringBase(pBuffer) { 32 | mBufferSize = size; 33 | 34 | if (size <= 0) { 35 | this->mString = nullptr; 36 | this->mBufferSize = 0; 37 | } 38 | else { 39 | assureTerminationImpl_(); 40 | } 41 | } 42 | 43 | virtual ~BufferedSafeStringBase() override = default; 44 | BufferedSafeStringBase& operator=(const SafeStringBase &) override; 45 | virtual void assureTerminationImpl_() const override; 46 | 47 | int mBufferSize; // _C 48 | }; 49 | }; 50 | 51 | typedef sead::SafeStringBase SafeString; -------------------------------------------------------------------------------- /include/sead/seadVector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace sead { 4 | template 5 | class Vector3 { 6 | public: 7 | T x; // _0 8 | T y; // _4 9 | T z; // _8 10 | }; 11 | }; 12 | 13 | typedef sead::Vector3 Vec3f; -------------------------------------------------------------------------------- /nso.py: -------------------------------------------------------------------------------- 1 | import os, struct, sys 2 | import lz4.block 3 | 4 | class SegmentHeader: 5 | fileOffset = 0 6 | memoryOffset = 0 7 | decompressedSize = 0 8 | 9 | def __init__(self, fileOffset, memoryOffset, decompressedSize): 10 | self.fileOffset = fileOffset 11 | self.memoryOffset = memoryOffset 12 | self.decompressedSize = decompressedSize 13 | 14 | class SegmentHeaderRelative: 15 | offset = 0 16 | size = 0 17 | 18 | def __init__(self, offset, size): 19 | self.offset = offset 20 | self.size = size 21 | 22 | class NSO: 23 | textSegmentHeader = None 24 | textData = [] 25 | rawData = None 26 | 27 | def __init__(self, nsoBinary): 28 | self.rawData = nsoBinary 29 | 30 | nsoStr = struct.unpack_from("4s", self.rawData, 0)[0].decode('latin-1') 31 | 32 | if nsoStr != "NSO0": 33 | print("Invalid NSO.") 34 | sys.exit(1) 35 | 36 | # we only need two things out of the header 37 | # 1) the offset and size of the text data within the binary (and its compressed size) 38 | # 2) whether or not we need to decompress the data 39 | flags = struct.unpack_from("= numCollectItem) 25 | return true; 26 | } 27 | 28 | return false; 29 | } -------------------------------------------------------------------------------- /source/Game/System/PlayerSelectType.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/System/PlayerSelectType.h" 2 | #include "Game/al/Util.h" 3 | 4 | int PlayerSelectType::calcPlayerSelectTypeID(const char *pType) { 5 | if (al::isEqualString(pType, "キノピオ")) 6 | return PLAYER_SELECT_TYPE_KINOPIO; 7 | 8 | if (al::isEqualString(pType, "キノピコ")) 9 | return PLAYER_SELECT_TYPE_KINOPICO; 10 | 11 | if (al::isEqualString(pType, "キノピオ&キノピコ")) 12 | return PLAYER_SELECT_TYPE_KINOPIO_AND_KINOPICO; 13 | 14 | return PLAYER_SELECT_TYPE_KINOPIO; 15 | } 16 | 17 | bool PlayerSelectType::isKinopio(const char *pType) { 18 | return al::isEqualString(pType, "キノピオ"); 19 | } 20 | 21 | bool PlayerSelectType::isKinopico(const char *pType) { 22 | return al::isEqualString(pType, "キノピコ"); 23 | } 24 | 25 | bool PlayerSelectType::isKinopioAndKinopico(const char *pType) { 26 | return al::isEqualString(pType, "キノピオ&キノピコ"); 27 | } -------------------------------------------------------------------------------- /source/Game/System/StageDatabaseInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/System/StageDatabaseInfo.h" 2 | #include "Game/System/BadgeConditionType.h" 3 | #include "Game/System/PlayerSelectType.h" 4 | #include "Game/System/StageType.h" 5 | #include "Game/al/Util.h" 6 | 7 | BadgeConditionInfo::BadgeConditionInfo() { 8 | mInfoCount = 0; 9 | mTypeIDs = new int[1]; 10 | mParams = new int[1]; 11 | *mTypeIDs = BADGE_CONDITION_TYPE_INVALID; 12 | *mParams = 0; 13 | } 14 | 15 | void BadgeConditionInfo::registerInfo(const char *pName, int param) { 16 | mTypeIDs[mInfoCount] = BadgeConditionType::calcBadgeConditionTypeID(pName); 17 | mParams[mInfoCount] = param; 18 | mInfoCount++; 19 | } 20 | 21 | int BadgeConditionInfo::getTypeID(int index) const { 22 | return mTypeIDs[index]; 23 | } 24 | 25 | int BadgeConditionInfo::getParam(int index) const { 26 | return mParams[index]; 27 | } 28 | 29 | #ifdef NON_MATCHING 30 | StageDatabaseInfo::StageDatabaseInfo() { 31 | mOpenPageNum = 1; 32 | mOffScreenBubble = true; 33 | mBadgeConditionInfo = new BadgeConditionInfo(); 34 | } 35 | #endif 36 | 37 | #ifdef NON_MATCHING // mStageType = StageType::calcStageTypeID loads the pointer param later than intended 38 | void StageDatabaseInfo::initialize(int seasonId, int stageId, int courseId, int pageId, int collectItemNum, 39 | int collectLockNum, int openPageNum, int challengeTime, int badgeCondition1Param, 40 | char const* pBadgeCondition1, char const* pStageName, char const* pStageType, char const* pPlayer, 41 | char const* pClipping, bool offScreenBubble, bool disableStageEntry, bool showGhostTutorial, 42 | bool isGhostBusterStage) 43 | { 44 | mSeasonId = seasonId; 45 | mStageId = stageId; 46 | mCollectItemNum = collectItemNum; 47 | mCollectLockNum = collectLockNum; 48 | mStageName = pStageName; 49 | mCourseId = courseId; 50 | mPageId = pageId; 51 | mOpenPageNum = openPageNum; 52 | mChallengeTime = challengeTime; 53 | mStageType = StageType::calcStageTypeID(pStageType); 54 | mPlayerSelectType = PlayerSelectType::calcPlayerSelectTypeID(pPlayer); 55 | mOffScreenBubble = offScreenBubble; 56 | mDisableStageEntry = disableStageEntry; 57 | mShowGhostTutorial = showGhostTutorial; 58 | mIsGhostBusterStage = isGhostBusterStage; 59 | 60 | if (!BadgeConditionType::isInvalid(pBadgeCondition1)) { 61 | mBadgeConditionInfo->registerInfo(pBadgeCondition1, badgeCondition1Param); 62 | } 63 | 64 | mIsValidClipping = !al::isEqualString(pClipping, "無効"); 65 | } 66 | #endif 67 | 68 | bool StageDatabaseInfo::isPlayerKinopio() const { 69 | return mPlayerSelectType == PLAYER_SELECT_TYPE_KINOPIO; 70 | } 71 | 72 | bool StageDatabaseInfo::isPlayerKinopico() const { 73 | return mPlayerSelectType == PLAYER_SELECT_TYPE_KINOPICO; 74 | } 75 | 76 | bool StageDatabaseInfo::isPlayerKinopioAndKinopico() const { 77 | return mPlayerSelectType == PLAYER_SELECT_TYPE_KINOPIO_AND_KINOPICO; 78 | } 79 | 80 | bool StageDatabaseInfo::isBadgeInvalid(int index) const { 81 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_INVALID; 82 | } 83 | 84 | bool StageDatabaseInfo::isBadgeCoinNum(int index) const { 85 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_COIN_NUM; 86 | } 87 | 88 | bool StageDatabaseInfo::isBadgeTouchNum(int index) const { 89 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_TOUCH_NUM; 90 | } 91 | 92 | bool StageDatabaseInfo::isBadgeOnSwitchChecker(int index) const { 93 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_ON_SWITCH_CHECKER; 94 | } 95 | 96 | bool StageDatabaseInfo::isBadgeOffSwitchChecker(int index) const { 97 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_OFF_SWITCH_CHECKER; 98 | } 99 | 100 | bool StageDatabaseInfo::isBadgeGetKinokoOneUp(int index) const { 101 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_GET_KINOKO_ONE_UP; 102 | } 103 | 104 | bool StageDatabaseInfo::isBadgeRadishThrowNum(int index) const { 105 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_RADISH_THROW_NUM; 106 | } 107 | 108 | bool StageDatabaseInfo::isBadgeNoDamage(int index) const { 109 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_NO_DAMAGE; 110 | } 111 | 112 | bool StageDatabaseInfo::isBadgeSwitchBlockNum(int index) const { 113 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_SWITCH_BLOCK_NUM; 114 | } 115 | 116 | bool StageDatabaseInfo::isBadgeDoubleCherryNum(int index) const { 117 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_DOUBLE_CHERRY_NUM; 118 | } 119 | 120 | bool StageDatabaseInfo::isBadgeGetKinokoTreasure(int index) const { 121 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_GET_KINOKO_TREASURE; 122 | } 123 | 124 | bool StageDatabaseInfo::isBadgeNoFoundHeyho(int index) const { 125 | return mBadgeConditionInfo->getTypeID(index) == BADGE_CONDITION_TYPE_NO_FOUND_HEYHO; 126 | } -------------------------------------------------------------------------------- /source/Game/System/StageType.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/System/StageType.h" 2 | #include "Game/al/Util.h" 3 | 4 | int StageType::calcStageTypeID(const char *pName) { 5 | if (al::isEqualString(pName, "通常")) { 6 | return STAGE_TYPE_NORMAL; 7 | } 8 | 9 | if (al::isEqualString(pName, "ボーナス")) { 10 | return STAGE_TYPE_BONUS; 11 | } 12 | 13 | if (al::isEqualString(pName, "ミニゲーム")) { 14 | return STAGE_TYPE_GAME_OVER_MINI_GAME; 15 | } 16 | 17 | if (al::isEqualString(pName, "挿絵デモ")) { 18 | return STAGE_TYPE_PICTURE_DEMO; 19 | } 20 | 21 | if (al::isEqualString(pName, "挿絵")) { 22 | return STAGE_TYPE_PICTURE; 23 | } 24 | 25 | if (al::isEqualString(pName, "プロローグ")) { 26 | return STAGE_TYPE_PROLOGUE; 27 | } 28 | 29 | if (al::isEqualString(pName, "特殊(3Dワールド)")) { 30 | return STAGE_TYPE_SPECIAL_3D_WORLD; 31 | } 32 | 33 | if (al::isEqualString(pName, "特殊(マネック)")) { 34 | return STAGE_TYPE_SPECIAL_MANECK; 35 | } 36 | 37 | if (al::isEqualString(pName, "特殊(チェリー)")) { 38 | return STAGE_TYPE_SPECIAL_CHERRY; 39 | } 40 | 41 | if (al::isEqualString(pName, "特殊(プロローグ)")) { 42 | return STAGE_TYPE_SPECIAL_PROLOGUE; 43 | } 44 | 45 | if (al::isEqualString(pName, "特殊(ボーナス)")) { 46 | return STAGE_TYPE_SPECIAL_BONUS; 47 | } 48 | 49 | if (al::isEqualString(pName, "特殊(その他)")) { 50 | return STAGE_TYPE_SPECIAL_OTHER; 51 | } 52 | 53 | if (al::isEqualString(pName, "トリックアート")) { 54 | return STAGE_TYPE_TRICK_ART; 55 | } 56 | 57 | if (al::isEqualString(pName, "白紙")) { 58 | return STAGE_TYPE_WHITE; 59 | } 60 | 61 | if (al::isEqualString(pName, "Labyrinth")) { 62 | return STAGE_TYPE_LABYRINTH; 63 | } 64 | 65 | return STAGE_TYPE_NORMAL; 66 | } 67 | 68 | bool StageType::isNormal(const char *pName) { 69 | return al::isEqualString(pName, "通常"); 70 | } 71 | 72 | bool StageType::isBonus(const char *pName) { 73 | return al::isEqualString(pName, "ボーナス"); 74 | } 75 | 76 | bool StageType::isGameOverMiniGame(const char *pName) { 77 | return al::isEqualString(pName, "ミニゲーム"); 78 | } 79 | 80 | bool StageType::isPictureDemo(const char *pName) { 81 | return al::isEqualString(pName, "挿絵デモ"); 82 | } 83 | 84 | bool StageType::isPicture(const char *pName) { 85 | return al::isEqualString(pName, "挿絵"); 86 | } 87 | 88 | bool StageType::isPrologue(const char *pName) { 89 | return al::isEqualString(pName, "プロローグ"); 90 | } 91 | 92 | bool StageType::isSpecial3DWorld(const char *pName) { 93 | return al::isEqualString(pName, "特殊(3Dワールド)"); 94 | } 95 | 96 | bool StageType::isSpecialManeck(const char *pName) { 97 | return al::isEqualString(pName, "特殊(マネック)"); 98 | } 99 | 100 | bool StageType::isSpecialCherry(const char *pName) { 101 | return al::isEqualString(pName, "特殊(チェリー)"); 102 | } 103 | 104 | bool StageType::isSpecialPrologue(const char *pName) { 105 | return al::isEqualString(pName, "特殊(プロローグ)"); 106 | } 107 | 108 | bool StageType::isSpecialBonus(const char *pName) { 109 | return al::isEqualString(pName, "特殊(ボーナス)"); 110 | } 111 | 112 | bool StageType::isSpecialOther(const char *pName) { 113 | return al::isEqualString(pName, "特殊(その他)"); 114 | } 115 | 116 | bool StageType::isTrickArt(const char *pName) { 117 | return al::isEqualString(pName, "トリックアート"); 118 | } 119 | 120 | bool StageType::isWhite(const char *pName) { 121 | return al::isEqualString(pName, "白紙"); 122 | } -------------------------------------------------------------------------------- /source/Game/System/StageUserData.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/System/StageUserData.h" 2 | #include "Game/Util.h" 3 | 4 | StageUserData::StageUserData() { 5 | mFigureType = kp::getPlayerFigureTypeDefault(); 6 | mIsAlive = false; 7 | } 8 | 9 | void StageUserData::init() { 10 | mFigureType = kp::getPlayerFigureTypeDefault(); 11 | mIsAlive = false; 12 | } 13 | 14 | void StageUserData::setFigureType(int figureType) { 15 | mFigureType = figureType; 16 | } 17 | 18 | void StageUserData::setAlive(bool alive) { 19 | mIsAlive = alive; 20 | } -------------------------------------------------------------------------------- /source/Game/System/StampType.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/System/StampType.h" 2 | #include "Game/al/Util.h" 3 | 4 | int StampType::calcStampTypeID(const char *pName) { 5 | if (al::isEqualString(pName, "Course")) { 6 | return STAMP_TYPE_COURSE; 7 | } 8 | if (al::isEqualString(pName, "Default")) { 9 | return STAMP_TYPE_DEFAULT; 10 | } 11 | if (al::isEqualString(pName, "MarioComplete")) { 12 | return STAMP_TYPE_MARIO_COMPLETE; 13 | } 14 | if (al::isEqualString(pName, "LuigiComplete")) { 15 | return STAMP_TYPE_LUIGI_COMPLETE; 16 | } 17 | if (al::isEqualString(pName, "PeachComplete")) { 18 | return STAMP_TYPE_PEACH_COMPLETE; 19 | } 20 | if (al::isEqualString(pName, "KinopioComplete")) { 21 | return STAMP_TYPE_KINOPIO_COMPLETE; 22 | } 23 | if (al::isEqualString(pName, "RosettaComplete")) { 24 | return STAMP_TYPE_ROSETTA_COMPLETE; 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | bool StampType::isCourse(const char *pName) { 31 | return al::isEqualString(pName, "Course"); 32 | } 33 | 34 | bool StampType::isDefault(const char *pName) { 35 | return al::isEqualString(pName, "Default"); 36 | } 37 | 38 | bool StampType::isMarioComplete(const char *pName) { 39 | return al::isEqualString(pName, "MarioComplete"); 40 | } 41 | 42 | bool StampType::isLuigiComplete(const char *pName) { 43 | return al::isEqualString(pName, "LuigiComplete"); 44 | } 45 | 46 | bool StampType::isPeachComplete(const char *pName) { 47 | return al::isEqualString(pName, "PeachComplete"); 48 | } 49 | 50 | bool StampType::isKinopioComplete(const char *pName) { 51 | return al::isEqualString(pName, "KinopioComplete"); 52 | } 53 | 54 | bool StampType::isRosettaComplete(const char *pName) { 55 | return al::isEqualString(pName, "RosettaComplete"); 56 | } -------------------------------------------------------------------------------- /source/Game/Util/PlayerUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/Util.h" 2 | 3 | int kp::getPlayerFigureTypeDefault() { 4 | return PLAYER_FIGURE_KINOPIO; 5 | } -------------------------------------------------------------------------------- /source/Game/al/LiveActor/HitSensor.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/LiveActor/HitSensor.h" 2 | #include "Game/al/LiveActor/SensorHitGroup.h" 3 | 4 | namespace al { 5 | void HitSensor::setFollowPosPtr(const Vec3f *pVec) { 6 | mFollowPos = pVec, mFollowMtx = nullptr; 7 | } 8 | 9 | void HitSensor::setFollowMtxPtr(const Matrix34f *pMtx) { 10 | mFollowPos = nullptr, mFollowMtx = pMtx; 11 | } 12 | 13 | void HitSensor::validate() { 14 | if (!_39) { 15 | _39 = 1; 16 | 17 | if (mMaxSensorCount && _38) { 18 | mHitGroup->add(this); 19 | } 20 | } 21 | 22 | mCurSensorCount = 0; 23 | } 24 | 25 | void HitSensor::invalidate() { 26 | if (_39) { 27 | _39 = 0; 28 | 29 | if (mMaxSensorCount && _38) { 30 | mHitGroup->remove(this); 31 | } 32 | } 33 | 34 | mCurSensorCount = 0; 35 | } 36 | 37 | void HitSensor::validateBySystem() { 38 | if (!_38) { 39 | if (mMaxSensorCount && _39) { 40 | mHitGroup->add(this); 41 | } 42 | 43 | _38 = 1; 44 | mCurSensorCount = 0; 45 | } 46 | } 47 | 48 | void HitSensor::invalidateBySystem() { 49 | if (_38) { 50 | if (mMaxSensorCount && _39) { 51 | mHitGroup->remove(this); 52 | } 53 | 54 | _38 = 0; 55 | mCurSensorCount = 0; 56 | } 57 | } 58 | 59 | void HitSensor::addHitSensor(al::HitSensor *pSensor) { 60 | if (mCurSensorCount < mMaxSensorCount) { 61 | mSensors[mCurSensorCount] = pSensor; 62 | mCurSensorCount++; 63 | } 64 | } 65 | }; -------------------------------------------------------------------------------- /source/Game/al/LiveActor/LiveActor.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/LiveActor/LiveActor.h" 2 | #include "Game/al/LiveActor/LiveActorFlag.h" 3 | #include 4 | 5 | namespace al { 6 | LiveActor::LiveActor(const char *pName) { 7 | mName = pName; 8 | mFlags = new LiveActorFlag(); 9 | } 10 | 11 | /*LiveActor::~LiveActor() { 12 | delete mFlags; 13 | delete mStageSwitchKeeper; 14 | delete mScreenPointKeeper; 15 | delete mHitSensorKeeper; 16 | delete mModelKeeper; 17 | delete mCollider; 18 | delete mScoreKeeper; 19 | delete mItemKeeper; 20 | }*/ 21 | 22 | void LiveActor::init(const ActorInitInfo &rInfo) { 23 | 24 | } 25 | }; -------------------------------------------------------------------------------- /source/Game/al/LiveActor/NerveExecutor.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/LiveActor/NerveExecutor.h" 2 | 3 | namespace al { 4 | NerveExecutor::NerveExecutor(const char *pName) { 5 | mNerveKeeper = nullptr; 6 | } 7 | 8 | NerveExecutor::~NerveExecutor() { 9 | delete mNerveKeeper; 10 | } 11 | 12 | void NerveExecutor::initNerve(const Nerve *pNerve, int a2) { 13 | mNerveKeeper = new NerveKeeper(this, pNerve, a2); 14 | } 15 | 16 | void NerveExecutor::updateNerve() { 17 | if (mNerveKeeper) { 18 | mNerveKeeper->update(); 19 | } 20 | } 21 | }; -------------------------------------------------------------------------------- /source/Game/al/LiveActor/NerveUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/LiveActor/NerveUtil.h" 2 | 3 | namespace al { 4 | void setNerve(IUseNerve *pUseNerve, const Nerve *pNerve) { 5 | pUseNerve->getNerveKeeper()->setNerve(pNerve); 6 | } 7 | 8 | void setNerveAtStep(IUseNerve *pUseNerve, const Nerve *pNerve, int step) { 9 | if (pUseNerve->getNerveKeeper()->mStep == step) { 10 | pUseNerve->getNerveKeeper()->setNerve(pNerve); 11 | } 12 | } 13 | 14 | bool isStep(const IUseNerve *pUseNerve, int step) { 15 | return pUseNerve->getNerveKeeper()->mStep == step; 16 | } 17 | 18 | bool isNerve(const IUseNerve *pUseNerve, const Nerve *pNerve) { 19 | return pUseNerve->getNerveKeeper()->getCurrentNerve() == pNerve; 20 | } 21 | 22 | int getNerveStep(const IUseNerve *pUseNerve) { 23 | return pUseNerve->getNerveKeeper()->mStep; 24 | } 25 | 26 | bool isFirstStep(const IUseNerve *pUseNerve) { 27 | return pUseNerve->getNerveKeeper()->mStep == 0; 28 | } 29 | 30 | bool isLessStep(const IUseNerve *pUseNerve, int step) { 31 | return pUseNerve->getNerveKeeper()->mStep < step; 32 | } 33 | 34 | bool isLessEqualStep(const IUseNerve *pUseNerve, int step) { 35 | return pUseNerve->getNerveKeeper()->mStep <= step; 36 | } 37 | 38 | bool isGreaterStep(const IUseNerve *pUseNerve, int step) { 39 | return pUseNerve->getNerveKeeper()->mStep > step; 40 | } 41 | 42 | bool isGreaterEqualStep(const IUseNerve *pUseNerve, int step) { 43 | return pUseNerve->getNerveKeeper()->mStep >= step; 44 | } 45 | 46 | bool isIntervalStep(const IUseNerve *pUseNerve, int interval, int startStep) { 47 | return (pUseNerve->getNerveKeeper()->mStep - startStep) % interval == 0; 48 | } 49 | 50 | bool isIntervalOnOffStep(const IUseNerve *pUseNerve, int interval, int startStep) { 51 | return ((pUseNerve->getNerveKeeper()->mStep - startStep) / interval & 1) == 0; 52 | } 53 | } -------------------------------------------------------------------------------- /source/Game/al/LiveActor/SensorHitGroup.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/LiveActor/SensorHitGroup.h" 2 | #include "Game/al/LiveActor/HitSensor.h" 3 | 4 | namespace al { 5 | SensorHitGroup::SensorHitGroup(int maxCount, const char *pUnused) { 6 | mMaxSensorCount = maxCount; 7 | mSensorCount = 0; 8 | mSensors = new al::HitSensor*[maxCount]; 9 | 10 | if (maxCount >= 1) { 11 | for (int i = 0; i < mMaxSensorCount; i++) { 12 | mSensors[i] = nullptr; 13 | } 14 | } 15 | } 16 | 17 | void SensorHitGroup::add(al::HitSensor *pSensor) { 18 | mSensors[mSensorCount] = pSensor; 19 | mSensorCount++; 20 | } 21 | 22 | al::HitSensor* SensorHitGroup::getSensor(int idx) const { 23 | return mSensors[idx]; 24 | } 25 | 26 | void SensorHitGroup::clear() const { 27 | if (mSensorCount >= 1) { 28 | for (int i = 0; i < mSensorCount; i++) { 29 | mSensors[i]->mCurSensorCount = 0; 30 | } 31 | } 32 | } 33 | }; -------------------------------------------------------------------------------- /source/Game/al/Util/StringUtil.cpp: -------------------------------------------------------------------------------- 1 | #include "Game/al/Util/StringUtil.h" 2 | #include 3 | 4 | namespace al { 5 | const char* getBaseName(const char *pName) { 6 | const char* str = strrchr(pName, '/'); 7 | return str ? str + 1 : pName; 8 | } 9 | 10 | #ifdef NON_MATCHING 11 | const char* createStringIfInStack(const char *pString) { 12 | if (isInStack(pString)) { 13 | size_t length = strlen(pString); 14 | char* buf = new char[length]; 15 | snprintf(buf, length, "%s", pString); 16 | return buf; 17 | } 18 | else { 19 | return pString; 20 | } 21 | } 22 | #endif 23 | 24 | void extractString(char *pDest, const char *pSource, unsigned int start, unsigned int end) { 25 | strncpy(pDest, pSource, start); 26 | pDest[start] = 0; 27 | } 28 | 29 | // al::searchSubString 30 | // al::searchSubString 31 | // al::getSubStringUnmatched 32 | // al::getSubStringUnmatched 33 | 34 | bool tryReplaceString(sead::BufferedSafeStringBase *pString, const char *a2, const char *a3) { 35 | pString->assureTerminationImpl_(); 36 | return tryReplaceString(pString, pString->mString, a2, a3); 37 | } 38 | 39 | // al::tryReplaceString 40 | // al::tryReplaceStringNoRecursive 41 | 42 | /*! 43 | @brief Compares two strings to see if they are the same. 44 | @return Returns whether the two strings are the same. 45 | */ 46 | bool isEqualString(const char16_t *pString_0, const char16_t *pString_1) { 47 | char16_t val; 48 | 49 | while (true) { 50 | val = *pString_0; 51 | 52 | if (val != *pString_1) { 53 | break; 54 | } 55 | 56 | ++pString_1; 57 | ++pString_0; 58 | 59 | if (!val) { 60 | return true; 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | 67 | /*! 68 | @brief Compares pString_1 to see if it is contained in pString_0. 69 | @return Returns whether or not pString_1 is contained in pString_1. 70 | */ 71 | bool isEqualSubString(const char *pString_0, const char *pString_1) { 72 | return strstr(pString_0, pString_1) != 0; 73 | } 74 | 75 | /*! 76 | @brief Compares rString_1 to see if it is contained in rString_0. 77 | @return Returns whether or not rString_1 is contained in rString_0. 78 | */ 79 | bool isEqualSubString(const SafeString &rString_0, const SafeString &rString_1) { 80 | return strstr(rString_0.cstr(), rString_1.cstr()) != 0; 81 | } 82 | 83 | /*! 84 | @brief Compares pString_0 to see if it starts with pString_1. 85 | @return Returns whether or not pString_0 starts with pString_1. 86 | */ 87 | bool isStartWithString(const char *pString_0, const char *pString_1) { 88 | if (!*pString_1) { 89 | return true; 90 | } 91 | 92 | while (*pString_0 && *pString_0 == *pString_1) { 93 | ++pString_0; 94 | ++pString_1; 95 | 96 | if (!*pString_1) { 97 | return true; 98 | } 99 | } 100 | 101 | return false; 102 | } 103 | 104 | /*! 105 | @brief Compares pString_0 to see if it ends with pString_1. 106 | @return Returns whether or not pString_0 ends with pString_1. 107 | */ 108 | bool isEndWithString(const char *pString_0, const char *pString_1) { 109 | int length_0 = strlen(pString_0); 110 | int length_1 = strlen(pString_1); 111 | 112 | if (length_0 < length_1) { 113 | return false; 114 | } 115 | 116 | // here we get the end of the strings since the second string is longer than the first 117 | return isEqualString(&pString_0[length_0 - length_1], pString_1); 118 | } 119 | 120 | // al::isMatchString 121 | 122 | /*! 123 | @brief Compares pString_0 to see if it matches pString_1, ignoring cases. 124 | @return Returns whether or not pString_0 matches with pString_1, ignoring cases. 125 | */ 126 | int compareStringIgnoreCase(const char *pString_0, const char *pString_1) { 127 | return strcasecmp(pString_0, pString_1); 128 | } 129 | 130 | // al::makeUrlEncodeString 131 | // al::makeUrlDecodeString 132 | 133 | /*! 134 | @brief Copies the string in pSource into the destination pDest. 135 | @return Nothing. 136 | */ 137 | void copyString(char *pDest, const char *pSource, unsigned int length) { 138 | strncpy(pDest, pSource, length); 139 | } 140 | 141 | // al::copyStringW 142 | // al::StringTmp dtor 143 | // al::isInStack 144 | 145 | /*! 146 | @brief Compares two strings to see if they are the same. 147 | @return Returns whether the two strings are the same. 148 | */ 149 | bool isEqualString(const char *pString_0, const char *pString_1) { 150 | char val; 151 | 152 | while (true) { 153 | val = *pString_0; 154 | 155 | if (val != *pString_1) { 156 | break; 157 | } 158 | 159 | ++pString_1; 160 | ++pString_0; 161 | 162 | if (!val) { 163 | return true; 164 | } 165 | } 166 | 167 | return false; 168 | } 169 | 170 | /*! 171 | @brief Compares two SafeStrings to see if they are the same. 172 | @return Returns whether the two SafeStrings are the same. 173 | */ 174 | bool isEqualString(const SafeString &rString_0, const SafeString &rString_1) { 175 | const char* str_0 = rString_0.cstr(); 176 | const char* str_1 = rString_1.cstr(); 177 | 178 | char val; 179 | 180 | while (true) { 181 | val = *str_0; 182 | 183 | if (val != *str_1) { 184 | break; 185 | } 186 | 187 | ++str_1; 188 | ++str_0; 189 | 190 | if (!val) { 191 | return true; 192 | } 193 | } 194 | 195 | return false; 196 | } 197 | 198 | /*! 199 | @brief Compares two strings to see if they contain the same casing. 200 | @return Returns whether the two strings contain the same casing. 201 | */ 202 | bool isEqualStringCase(const char *pString_0, const char *pString_1) { 203 | return strcasecmp(pString_0, pString_1) == 0; 204 | } 205 | 206 | /*! 207 | @brief Compares two SafeStrings to see if they contain the same casing. 208 | @return Returns whether the two SafeStrings contain the same casing. 209 | */ 210 | bool isEqualStringCase(const SafeString &rString_0, const SafeString &rString_1) { 211 | return strcasecmp(rString_0.cstr(), rString_1.cstr()) == 0; 212 | } 213 | }; --------------------------------------------------------------------------------