├── .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 |
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 | };
--------------------------------------------------------------------------------