├── .gitattributes ├── .gitignore ├── LICENSE ├── config └── GLME01 │ ├── build.sha1 │ ├── config.yml │ ├── splits.txt │ └── symbols.txt ├── configure.py ├── include ├── JSystem │ └── JHostIOD │ │ └── JORServer.h ├── Koga │ ├── CharacterEventObserver.h │ └── Observer.h ├── MSL_C │ ├── MSL_Common │ │ └── Src │ │ │ ├── FILE_POS.h │ │ │ ├── abort_exit.h │ │ │ ├── alloc.h │ │ │ ├── ansi_files.h │ │ │ ├── arith.h │ │ │ ├── buffer_io.h │ │ │ ├── char_io.h │ │ │ ├── ctype.h │ │ │ ├── direct_io.h │ │ │ ├── extras.h │ │ │ ├── file_io.h │ │ │ ├── float.h │ │ │ ├── limits │ │ │ ├── mbstring.h │ │ │ ├── mem.h │ │ │ ├── mem_funcs.h │ │ │ ├── misc_io.h │ │ │ ├── printf.h │ │ │ ├── scanf.h │ │ │ ├── signal.h │ │ │ ├── stddef.h │ │ │ ├── string.h │ │ │ ├── strtoul.h │ │ │ └── wchar_io.h │ ├── MSL_Common_Embedded │ │ └── Src │ │ │ └── ansi_fp.h │ ├── Math │ │ └── Double_precision │ │ │ ├── e_acos.h │ │ │ ├── e_asin.h │ │ │ ├── e_atan2.h │ │ │ ├── e_exp.h │ │ │ ├── e_fmod.h │ │ │ ├── e_pow.h │ │ │ ├── e_rem_pio2.h │ │ │ ├── e_sqrt.h │ │ │ ├── k_cos.h │ │ │ ├── k_rem_pio2.h │ │ │ ├── k_sin.h │ │ │ ├── k_tan.h │ │ │ ├── s_atan.h │ │ │ ├── s_ceil.h │ │ │ ├── s_copysign.h │ │ │ ├── s_cos.h │ │ │ ├── s_floor.h │ │ │ ├── s_frexp.h │ │ │ ├── s_ldexp.h │ │ │ ├── s_modf.h │ │ │ ├── s_sin.h │ │ │ ├── s_tan.h │ │ │ ├── w_acos.h │ │ │ ├── w_asin.h │ │ │ ├── w_atan2.h │ │ │ ├── w_exp.h │ │ │ ├── w_fmod.h │ │ │ ├── w_pow.h │ │ │ └── w_sqrt.h │ ├── PPC_EABI │ │ └── Src │ │ │ ├── critical_regions.gamecube.h │ │ │ ├── math_ppc.h │ │ │ └── uart_console_io_gcn.h │ ├── algorithm.h │ ├── bitset.h │ ├── float.h │ ├── functional.h │ ├── math.h │ ├── stdio.h │ ├── stdlib.h │ ├── string.h │ └── utility.h ├── Sato │ ├── EnStrategy.h │ ├── EnemyStrategy.h │ └── EnemyTypicalStrategy.h ├── Sotoike │ └── AITurara.h ├── Unsorted │ └── IncludeStrategy.h └── dolphin │ └── types.h ├── orig └── GLME01 │ └── .gitkeep ├── src ├── Koga │ └── CharacterEventObserver.cpp ├── Sato │ ├── EnStrategy.cpp │ ├── EnemyStrategy.cpp │ └── EnemyTypicalStrategy.cpp ├── Sotoike │ └── AITurara.cpp ├── Unsorted │ └── IncludeStrategy.cpp └── hvqm4dec │ └── hvqm4dec.c └── tools ├── __init__.py ├── decompctx.py ├── download_tool.py ├── ninja_syntax.py ├── project.py ├── transform_dep.py └── upload_progress.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Explicitly declare text files 5 | *.py text 6 | 7 | # Enforce platform-specific encodings 8 | *.bat text eol=crlf 9 | *.sh text eol=lf 10 | *.sha1 text eol=lf 11 | 12 | # DTK keeps these files with LF 13 | config/**/*.txt text eol=lf 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .idea 3 | .vscode 4 | .ninja_* 5 | *.exe 6 | build 7 | build.ninja 8 | objdiff.json 9 | orig/*/* 10 | !orig/*/.gitkeep 11 | /*.txt 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /config/GLME01/build.sha1: -------------------------------------------------------------------------------- 1 | 77d49225e7d28b9777916cdbe5809345c570ecbc build/GLME01/main.dol 2 | -------------------------------------------------------------------------------- /config/GLME01/config.yml: -------------------------------------------------------------------------------- 1 | # See config.example.yml for documentation. 2 | object: orig/GLME01/sys/main.dol 3 | hash: 77d49225e7d28b9777916cdbe5809345c570ecbc 4 | symbols: config/GLME01/symbols.txt 5 | splits: config/GLME01/splits.txt 6 | mw_comment_version: 8 7 | 8 | quick_analysis: true 9 | detect_objects: true 10 | detect_strings: true 11 | 12 | -------------------------------------------------------------------------------- /config/GLME01/splits.txt: -------------------------------------------------------------------------------- 1 | Sections: 2 | .init type:code 3 | extab type:rodata 4 | extabindex type:rodata 5 | .text type:code 6 | .ctors type:rodata 7 | .dtors type:rodata 8 | .rodata type:rodata 9 | .data type:data 10 | .bss type:bss 11 | .sdata type:data 12 | .sbss type:bss 13 | .sdata2 type:rodata 14 | 15 | Unsorted/MoveObj.cpp: 16 | .text start:0x800677D0 end:0x80068EF8 17 | 18 | Unsorted/Character.cpp: 19 | .text start:0x80068EF8 end:0x8006A354 20 | 21 | Sotoike/AIGirl.cpp: 22 | .text start:0x8006A594 end:0x8006ADDC 23 | .ctors start:0x8020BB44 end:0x8020BB48 24 | 25 | Sotoike/AIShower.cpp: 26 | .text start:0x8006ADDC end:0x8006BD40 27 | .ctors start:0x8020BB48 end:0x8020BB4C 28 | 29 | Sotoike/AITubone.cpp: 30 | .text start:0x8006BD40 end:0x8006C190 31 | .ctors start:0x8020BB4C end:0x8020BB50 32 | 33 | Sotoike/AIFire.cpp: 34 | .text start:0x8006C190 end:0x8006DDC8 35 | .ctors start:0x8020BB50 end:0x8020BB54 36 | 37 | Sotoike/AIShadow.cpp: 38 | .text start:0x8006DDC8 end:0x8006F298 39 | .ctors start:0x8020BB54 end:0x8020BB58 40 | 41 | Sotoike/AITurara.cpp: 42 | .text start:0x8006F298 end:0x8006F9D4 43 | .ctors start:0x8020BB58 end:0x8020BB5C 44 | .data start:0x8034C308 end:0x8034C570 45 | .sdata start:0x804D1E60 end:0x804D1EB8 46 | 47 | Sotoike/AIFall.cpp: 48 | .text start:0x8006F9D4 end:0x80070398 49 | .ctors start:0x8020BB5C end:0x8020BB60 50 | 51 | Sotoike/AISnowman.cpp: 52 | .text start:0x80070398 end:0x80071A00 53 | .ctors start:0x8020BB60 end:0x8020BB64 54 | 55 | Sotoike/AIIce.cpp: 56 | .text start:0x80071A00 end:0x80071E80 57 | .ctors start:0x8020BB64 end:0x8020BB68 58 | 59 | Sotoike/AILamp.cpp: 60 | .text start:0x80071E80 end:0x8007214C 61 | .ctors start:0x8020BB68 end:0x8020BB6C 62 | 63 | Kawamoto/KtEnTsuri.cpp: 64 | .text start:0x800986BC end:0x8009A874 65 | .ctors start:0x8020BB80 end:0x8020BB84 66 | 67 | Kawamoto/KtEnKihon.cpp: 68 | .text start:0x8009A874 end:0x8009B678 69 | .ctors start:0x8020BB84 end:0x8020BB88 70 | 71 | Kawamoto/KtEnUranai.cpp: 72 | .text start:0x8009B678 end:0x8009BC0C 73 | 74 | Kawamoto/KtEnObaasan.cpp: 75 | .text start:0x8009BC0C end:0x8009CAAC 76 | 77 | Kawamoto/KtEnKeito.cpp: 78 | .text start:0x8009CAAC end:0x8009D450 79 | .ctors start:0x8020BB88 end:0x8020BB8C 80 | 81 | Kawamoto/KtEnGaka.cpp: 82 | .text start:0x8009D450 end:0x8009D848 83 | 84 | Kawamoto/KtEnTubone.cpp: 85 | .text start:0x8009D848 end:0x8009DD18 86 | 87 | Kawamoto/KtEnDenwa.cpp: 88 | .text start:0x8009DD18 end:0x8009E024 89 | 90 | Kawamoto/KtEnIsu02.cpp: 91 | .text start:0x8009E024 end:0x8009E180 92 | 93 | Kawamoto/KtEnBaby.cpp: 94 | .text start:0x8009E180 end:0x800A0658 95 | .ctors start:0x8020BB8C end:0x8020BB90 96 | 97 | Kawamoto/KtEnMoku.cpp: 98 | .text start:0x800A0658 end:0x800A1F28 99 | .ctors start:0x8020BB90 end:0x8020BB94 100 | 101 | Kawamoto/KtEnMoku2.cpp: 102 | .text start:0x800A1F28 end:0x800A2218 103 | .ctors start:0x8020BB94 end:0x8020BB98 104 | 105 | Kawamoto/KtEnBabyball.cpp: 106 | .text start:0x800A2218 end:0x800A3BC0 107 | .ctors start:0x8020BB98 end:0x8020BB9C 108 | 109 | Kawamoto/KtEnKoopa.cpp: 110 | .text start:0x800A3BC0 end:0x800A7120 111 | .ctors start:0x8020BB9C end:0x8020BBA0 112 | 113 | Kawamoto/KtEnKoopahead.cpp: 114 | .text start:0x800A7120 end:0x800A8A3C 115 | .ctors start:0x8020BBA0 end:0x8020BBA4 116 | 117 | Kawamoto/KtEnKoopabomb.cpp: 118 | .text start:0x800A8A3C end:0x800A9C7C 119 | .ctors start:0x8020BBA4 end:0x8020BBA8 120 | 121 | Kawamoto/KtEnPillar.cpp: 122 | .text start:0x800A9C7C end:0x800AA128 123 | .ctors start:0x8020BBA8 end:0x8020BBAC 124 | 125 | Kawamoto/KtStatic.cpp: 126 | .text start:0x800AA128 end:0x800AAF5C 127 | 128 | Kawamoto/KtUnkB0C0.cpp: 129 | .text start:0x800AB0C0 end:0x800AB71C 130 | 131 | Kawamoto/KtOyadama.cpp: 132 | .text start:0x800AB71C end:0x800AC0F0 133 | 134 | Unsorted/Player.cpp: 135 | .text start:0x800AD5AC end:0x800B9D1C 136 | .ctors start:0x8020BBAC end:0x8020BBB0 137 | 138 | Koga/MissionModeUtil.cpp: 139 | .text start:0x800B9D1C end:0x800B9E0C 140 | 141 | Koga/GameModeUtil.cpp: 142 | .text start:0x800B9E0C end:0x800B9F7C 143 | 144 | Unsorted/MapDoors.cpp: 145 | .text start:0x800B9F7C end:0x800BA2D4 146 | 147 | Unsorted/IncludeStrategy.cpp: 148 | .text start:0x800BEBF4 end:0x800BED48 149 | 150 | Sato/EnemyStrategy.cpp: 151 | .text start:0x800C2224 end:0x800C24A4 152 | .data start:0x8035A4E0 end:0x8035A598 153 | .sdata start:0x804D2E60 end:0x804D2E78 154 | 155 | Sato/EnemyTypicalStrategy.cpp: 156 | .text start:0x800C6A28 end:0x800C6A98 157 | .data start:0x8035B0D8 end:0x8035B278 158 | .sdata start:0x804D3018 end:0x804D3048 159 | 160 | Sato/EnStrategy.cpp: 161 | .text start:0x800E4040 end:0x800E44C8 162 | .data start:0x803639B8 end:0x80363B04 163 | .sdata start:0x804D3D98 end:0x804D3DB8 164 | 165 | Koga/CharacterEventObserver.cpp: 166 | .text start:0x800EA1B4 end:0x800EA454 167 | .data start:0x80363FA0 end:0x803640D4 168 | .sdata start:0x804D3F68 end:0x804D3F78 169 | 170 | hvqm4dec/hvqm4dec.c: 171 | .text start:0x801FA5EC end:0x80200094 172 | 173 | Runtime.PPCEABI.H/__init_cpp_exceptions.cpp: 174 | .text start:0x8020265C end:0x802026D8 175 | .ctors start:0x8020BAC0 end:0x8020BAC4 176 | .dtors start:0x8020BDE0 end:0x8020BDE8 177 | .sdata start:0x804D7FB0 end:0x804D7FB8 178 | -------------------------------------------------------------------------------- /configure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ### 4 | # Generates build files for the project. 5 | # This file also includes the project configuration, 6 | # such as compiler flags and the object matching status. 7 | # 8 | # Usage: 9 | # python3 configure.py 10 | # ninja 11 | # 12 | # Append --help to see available options. 13 | ### 14 | 15 | import sys 16 | import argparse 17 | 18 | from pathlib import Path 19 | from tools.project import ( 20 | Object, 21 | ProjectConfig, 22 | calculate_progress, 23 | generate_build, 24 | is_windows, 25 | ) 26 | 27 | # Game versions 28 | DEFAULT_VERSION = 0 29 | VERSIONS = [ 30 | "GLME01", # 0 31 | ] 32 | 33 | if len(VERSIONS) > 1: 34 | versions_str = ", ".join(VERSIONS[:-1]) + f" or {VERSIONS[-1]}" 35 | else: 36 | versions_str = VERSIONS[0] 37 | 38 | parser = argparse.ArgumentParser() 39 | parser.add_argument( 40 | "mode", 41 | default="configure", 42 | help="configure or progress (default: configure)", 43 | nargs="?", 44 | ) 45 | parser.add_argument( 46 | "--version", 47 | dest="version", 48 | default=VERSIONS[DEFAULT_VERSION], 49 | help=f"version to build ({versions_str})", 50 | ) 51 | parser.add_argument( 52 | "--build-dir", 53 | dest="build_dir", 54 | type=Path, 55 | default=Path("build"), 56 | help="base build directory (default: build)", 57 | ) 58 | parser.add_argument( 59 | "--compilers", 60 | dest="compilers", 61 | type=Path, 62 | help="path to compilers (optional)", 63 | ) 64 | parser.add_argument( 65 | "--map", 66 | dest="map", 67 | action="store_true", 68 | help="generate map file(s)", 69 | ) 70 | parser.add_argument( 71 | "--debug", 72 | dest="debug", 73 | action="store_true", 74 | help="build with debug info (non-matching)", 75 | ) 76 | if not is_windows(): 77 | parser.add_argument( 78 | "--wrapper", 79 | dest="wrapper", 80 | type=Path, 81 | help="path to wibo or wine (optional)", 82 | ) 83 | parser.add_argument( 84 | "--build-dtk", 85 | dest="build_dtk", 86 | type=Path, 87 | help="path to decomp-toolkit source (optional)", 88 | ) 89 | parser.add_argument( 90 | "--sjiswrap", 91 | dest="sjiswrap", 92 | type=Path, 93 | help="path to sjiswrap.exe (optional)", 94 | ) 95 | parser.add_argument( 96 | "--verbose", 97 | dest="verbose", 98 | action="store_true", 99 | help="print verbose output", 100 | ) 101 | args = parser.parse_args() 102 | 103 | config = ProjectConfig() 104 | config.version = args.version.upper() 105 | if config.version not in VERSIONS: 106 | sys.exit(f"Invalid version '{config.version}', expected {versions_str}") 107 | version_num = VERSIONS.index(config.version) 108 | 109 | # Apply arguments 110 | config.build_dir = args.build_dir 111 | config.build_dtk_path = args.build_dtk 112 | config.compilers_path = args.compilers 113 | config.debug = args.debug 114 | config.generate_map = args.map 115 | config.sjiswrap_path = args.sjiswrap 116 | if not is_windows(): 117 | config.wrapper = args.wrapper 118 | 119 | # Tool versions 120 | config.compilers_tag = "20230715" 121 | config.dtk_tag = "v0.5.7" 122 | config.sjiswrap_tag = "v1.1.1" 123 | config.wibo_tag = "0.6.3" 124 | 125 | # Project 126 | config.config_path = Path("config") / config.version / "config.yml" 127 | config.check_sha_path = Path("config") / config.version / "build.sha1" 128 | config.ldflags = [ 129 | "-fp hardware", 130 | "-nodefaults", 131 | ] 132 | 133 | # Base flags, common to most GC/Wii games. 134 | # Generally leave untouched, with overrides added below. 135 | cflags_base = [ 136 | "-nodefaults", 137 | "-proc gekko", 138 | "-align powerpc", 139 | "-enum int", 140 | "-fp hardware", 141 | "-Cpp_exceptions off", 142 | # "-W all", 143 | "-O4,p", 144 | "-inline auto", 145 | '-pragma "cats off"', 146 | '-pragma "warn_notinlined off"', 147 | "-maxerrors 1", 148 | "-nosyspath", 149 | "-RTTI off", 150 | "-fp_contract on", 151 | "-str reuse", 152 | "-i include", 153 | "-multibyte", 154 | f"-DVERSION={version_num}", 155 | ] 156 | 157 | # Debug flags 158 | if config.debug: 159 | cflags_base.extend(["-sym on", "-DDEBUG=1"]) 160 | else: 161 | cflags_base.append("-DNDEBUG=1") 162 | 163 | # Metrowerks library flags 164 | cflags_runtime = [ 165 | *cflags_base, 166 | "-use_lmw_stmw on", 167 | "-str reuse,pool", 168 | "-common off", 169 | "-inline auto", 170 | ] 171 | 172 | # Game flags 173 | cflags_game = [ 174 | *cflags_base, 175 | "-RTTI on" 176 | ] 177 | 178 | config.linker_version = "GC/1.1" 179 | 180 | 181 | # Helper function for Dolphin libraries 182 | def DolphinLib(lib_name, objects): 183 | return { 184 | "lib": lib_name, 185 | "mw_version": "GC/1.1", 186 | "cflags": cflags_base, 187 | "objects": objects, 188 | } 189 | 190 | 191 | Matching = True 192 | NonMatching = False 193 | 194 | config.warn_missing_config = True 195 | config.warn_missing_source = False 196 | config.libs = [ 197 | { 198 | "lib": "zmansion", 199 | "mw_version": config.linker_version, 200 | "cflags": cflags_game, 201 | "objects": [ 202 | Object(NonMatching, "Unsorted/MoveObj.cpp"), 203 | Object(NonMatching, "Unsorted/Character.cpp"), 204 | Object(Matching, "Sato/EnemyStrategy.cpp"), 205 | Object(NonMatching, "Unsorted/IncludeStrategy.cpp"), 206 | Object(NonMatching, "Sato/EnStrategy.cpp"), 207 | Object(NonMatching, "Sato/EnemyTypicalStrategy.cpp"), 208 | Object(NonMatching, "Sotoike/AITurara.cpp"), 209 | Object(Matching, "Koga/CharacterEventObserver.cpp"), 210 | Object(NonMatching, "hvqm4dec/hvqm4dec.c"), 211 | ], 212 | }, 213 | { 214 | "lib": "Runtime.PPCEABI.H", 215 | "mw_version": config.linker_version, 216 | "cflags": cflags_runtime, 217 | "objects": [ 218 | Object(NonMatching, "Runtime.PPCEABI.H/global_destructor_chain.c"), 219 | Object(NonMatching, "Runtime.PPCEABI.H/__init_cpp_exceptions.cpp"), 220 | ], 221 | }, 222 | ] 223 | 224 | if args.mode == "configure": 225 | # Write build.ninja and objdiff.json 226 | generate_build(config) 227 | elif args.mode == "progress": 228 | # Print progress and write progress.json 229 | config.progress_each_module = args.verbose 230 | calculate_progress(config) 231 | else: 232 | sys.exit("Unknown mode: " + args.mode) 233 | -------------------------------------------------------------------------------- /include/JSystem/JHostIOD/JORServer.h: -------------------------------------------------------------------------------- 1 | #ifndef JOR_SERVER_H_ 2 | #define JOR_SERVER_H_ 3 | 4 | class JORReflexible 5 | { 6 | 7 | }; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/Koga/CharacterEventObserver.h: -------------------------------------------------------------------------------- 1 | #ifndef CHARACTER_EVENT_OBSERVER_H_ 2 | #define CHARACTER_EVENT_OBSERVER_H_ 3 | 4 | #include "Koga/Observer.h" 5 | 6 | namespace Koga 7 | { 8 | class CharacterEvent 9 | { 10 | public: 11 | CharacterEvent(const int& message); 12 | 13 | int mMessage; 14 | int mUnk1; 15 | int mUnk2; 16 | int mUnk3; 17 | int mUnk4; 18 | int mUnk5; 19 | int mUnk6; 20 | 21 | bool* mUnknownEntityBools; 22 | }; 23 | 24 | class CharacterEventObserver : public Observer 25 | { 26 | public: 27 | virtual bool receiveMessage(CharacterEvent* msg); 28 | 29 | /* Called while the actor is inside the flashlight cone. */ 30 | virtual bool onEnteredFlashlightBeam(CharacterEvent* msg); 31 | 32 | /* Called when the actor's HP hits 0 while being fished. */ 33 | virtual bool onCaptureBegin(CharacterEvent* msg); 34 | /* Called when the actor has been sucked into the Poltergust. */ 35 | virtual bool onCaptureEnd(CharacterEvent* msg); 36 | 37 | /* TODO: What does this do? */ 38 | virtual bool FUN_800ea380(CharacterEvent* msg); 39 | 40 | /* Called when the actor collides with the player. */ 41 | virtual bool onCollideWithPlayer(CharacterEvent* msg); 42 | 43 | /* Called when the actor is exposed to fire. */ 44 | virtual bool onSprayedWithFire(CharacterEvent* msg); 45 | /* Called when the actor is exposed to ice. */ 46 | virtual bool onSprayedWithIce(CharacterEvent* msg); 47 | /* Called when the actor is exposed to water. */ 48 | virtual bool onSprayedWithWater(CharacterEvent* msg); 49 | 50 | /* Called when the actor is hit with a fire elemental ball. */ 51 | virtual bool onHitWithFireBall(CharacterEvent* msg); 52 | /* Called when the actor is hit with an ice elemental ball. */ 53 | virtual bool onHitWithIceBall(CharacterEvent* msg); 54 | /* Called when the actor is hit with a water elemental ball. */ 55 | virtual bool onHitWithWaterBall(CharacterEvent* msg); 56 | 57 | /* Called when the actor is hooked by the Poltergust. */ 58 | virtual bool onFishingBegin(CharacterEvent* msg); 59 | 60 | /* Called when the player leaves the actor's current room. */ 61 | virtual bool onPlayerLeftRoom(CharacterEvent* msg); 62 | /* Called when the player enters the actor's current room. */ 63 | virtual bool onPlayerEnteredRoom(CharacterEvent* msg); 64 | 65 | /* Called when the player presses the A button on the actor; treasure chests only? */ 66 | virtual bool onPlayerTapped(CharacterEvent* msg); 67 | 68 | /* TODO: What does this do? */ 69 | virtual bool FUN_800ea44c(CharacterEvent* msg); 70 | }; 71 | } 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /include/Koga/Observer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBSERVER_H_ 2 | #define OBSERVER_H_ 3 | 4 | namespace Koga 5 | { 6 | template 7 | class Observer 8 | { 9 | public: 10 | virtual Ret receiveMessage(Msg* msg) = 0; 11 | }; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/FILE_POS.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_FILE_POS_H 2 | #define MSL_COMMON_SRC_FILE_POS_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int fseek(FILE* file, long offset, int mode); 11 | int _fseek(FILE* file, fpos_t offset, int mode); 12 | long ftell(FILE* file); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* MSL_COMMON_SRC_FILE_POS_H */ 19 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/abort_exit.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_ABORT_EXIT_H 2 | #define MSL_COMMON_SRC_ABORT_EXIT_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void exit(int status); 9 | void abort(void); 10 | 11 | extern void (*__stdio_exit)(void); 12 | 13 | #ifdef __cplusplus 14 | }; 15 | #endif 16 | 17 | #endif /* MSL_COMMON_SRC_ABORT_EXIT_H */ 18 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/alloc.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_ALLOC_H 2 | #define MSL_COMMON_SRC_ALLOC_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void free(FILE* file); 11 | void __pool_free(int** param_1, unsigned int** param_2); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* MSL_COMMON_SRC_ALLOC_H */ 18 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/ansi_files.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_ANSI_FILES_H 2 | #define MSL_COMMON_SRC_ANSI_FILES_H 3 | 4 | #include "MSL_C/MSL_Common/Src/stddef.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define SEEK_SET 0 11 | #define SEEK_CUR 1 12 | #define SEEK_END 2 13 | 14 | typedef unsigned long __file_handle; 15 | typedef unsigned long fpos_t; 16 | #ifndef __cplusplus 17 | typedef unsigned short wchar_t; 18 | #endif 19 | 20 | #define set_error(file) \ 21 | do { \ 22 | (file)->file_state.error = 1; \ 23 | (file)->buffer_length = 0; \ 24 | } while (0) 25 | 26 | enum __file_kinds { 27 | __closed_file, 28 | __disk_file, 29 | __console_file, 30 | __unavailable_file, 31 | }; 32 | 33 | enum __file_orientation { 34 | /* 0x0 */ UNORIENTED, 35 | /* 0x1 */ CHAR_ORIENTED, 36 | /* 0x2 */ WIDE_ORIENTED, 37 | }; 38 | 39 | typedef struct _file_modes { 40 | unsigned int open_mode : 2; 41 | unsigned int io_mode : 3; 42 | unsigned int buffer_mode : 2; 43 | unsigned int file_kind : 3; 44 | unsigned int file_orientation : 2; 45 | unsigned int binary_io : 1; 46 | } file_modes; 47 | 48 | enum __io_modes { 49 | __read = 1, 50 | __write = 2, 51 | __read_write = 3, 52 | __append = 4, 53 | }; 54 | 55 | enum __io_states { 56 | __neutral, 57 | __writing, 58 | __reading, 59 | __rereading, 60 | }; 61 | 62 | enum __io_results { 63 | __no_io_error, 64 | __io_error, 65 | __io_EOF, 66 | }; 67 | 68 | typedef struct _file_states { 69 | unsigned int io_state : 3; 70 | unsigned int free_buffer : 1; 71 | unsigned char eof; 72 | unsigned char error; 73 | } file_states; 74 | 75 | typedef void (*__idle_proc)(void); 76 | typedef int (*__pos_proc)(__file_handle file, fpos_t* position, int mode, __idle_proc idle_proc); 77 | typedef int (*__io_proc)(__file_handle file, unsigned char* buff, size_t* count, 78 | __idle_proc idle_proc); 79 | typedef int (*__close_proc)(__file_handle file); 80 | 81 | typedef struct _FILE { 82 | /* 0x00 */ __file_handle handle; 83 | /* 0x04 */ file_modes file_mode; 84 | /* 0x08 */ file_states file_state; 85 | /* 0x0C */ unsigned char is_dynamically_allocated; 86 | /* 0x0D */ char char_buffer; 87 | /* 0x0E */ char char_buffer_overflow; 88 | /* 0x0F */ char ungetc_buffer[2]; 89 | /* 0x12 */ wchar_t ungetc_wide_buffer[2]; 90 | /* 0x18 */ unsigned long position; 91 | /* 0x1C */ unsigned char* buffer; 92 | /* 0x20 */ unsigned long buffer_size; 93 | /* 0x24 */ unsigned char* buffer_ptr; 94 | /* 0x28 */ unsigned long buffer_length; 95 | /* 0x2C */ unsigned long buffer_alignment; 96 | /* 0x30 */ unsigned long save_buffer_length; 97 | /* 0x34 */ unsigned long buffer_position; 98 | /* 0x38 */ __pos_proc position_fn; 99 | /* 0x3C */ __io_proc read_fn; 100 | /* 0x40 */ __io_proc write_fn; 101 | /* 0x44 */ __close_proc close_fn; 102 | /* 0x48 */ __idle_proc idle_fn; 103 | /* 0x4C */ struct _FILE* next_file; 104 | } FILE; 105 | 106 | typedef struct _files { 107 | FILE _stdin; 108 | FILE _stdout; 109 | FILE _stderr; 110 | FILE empty; 111 | } files; 112 | 113 | #define _IONBF 0 114 | #define _IOLBF 1 115 | #define _IOFBF 2 116 | 117 | extern files __files; 118 | extern int __close_console(__file_handle file); 119 | extern int __write_console(__file_handle file, unsigned char* buf, size_t* count, 120 | __idle_proc idle_fn); 121 | extern int __read_console(__file_handle file, unsigned char* buf, size_t* count, 122 | __idle_proc idle_fn); 123 | 124 | unsigned int __flush_all(void); 125 | void __close_all(void); 126 | 127 | #ifdef __cplusplus 128 | }; 129 | #endif 130 | 131 | #endif /* MSL_COMMON_SRC_ANSI_FILES_H */ 132 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/arith.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_ARITH_H 2 | #define MSL_COMMON_SRC_ARITH_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { 9 | int quot; /* quotient */ 10 | int rem; /* remainder */ 11 | } div_t; 12 | 13 | div_t div(int numerator, int denominator); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* MSL_COMMON_SRC_ARITH_H */ 20 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/buffer_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_BUFFER_IO_H 2 | #define MSL_COMMON_SRC_BUFFER_IO_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | enum { __align_buffer, __dont_align_buffer }; 7 | 8 | void __prep_buffer(FILE* file); 9 | int __flush_buffer(FILE* file, size_t* bytes_flushed); 10 | 11 | #endif /* MSL_COMMON_SRC_BUFFER_IO_H */ 12 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/char_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_CHAR_IO_H 2 | #define MSL_COMMON_SRC_CHAR_IO_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int fputs(const char* str, FILE* stream); 11 | int __put_char(int c, FILE* stream); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* MSL_COMMON_SRC_CHAR_IO_H */ 18 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_CTYPE_H 2 | #define MSL_COMMON_SRC_CTYPE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define EOF -1L 9 | 10 | extern unsigned char __ctype_map[]; 11 | extern unsigned char __lower_map[]; 12 | extern unsigned char __upper_map[]; 13 | 14 | #define __control_char 0x01 15 | #define __motion_char 0x02 16 | #define __space_char 0x04 17 | #define __punctuation 0x08 18 | #define __digit 0x10 19 | #define __hex_digit 0x20 20 | #define __lower_case 0x40 21 | #define __upper_case 0x80 22 | 23 | #define __letter (__lower_case | __upper_case) 24 | #define __alphanumeric (__letter | __digit) 25 | #define __graphic (__alphanumeric | __punctuation) 26 | #define __printable (__graphic | __space_char) 27 | #define __whitespace (__motion_char | __space_char) 28 | #define __control (__motion_char | __control_char) 29 | #define __zero_fill(c) ((int)(unsigned char)(c)) 30 | 31 | int tolower(int); 32 | 33 | #ifdef __cplusplus 34 | } 35 | #endif 36 | 37 | #endif /* MSL_COMMON_SRC_CTYPE_H */ 38 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/direct_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_DIRECT_IO_H 2 | #define MSL_COMMON_SRC_DIRECT_IO_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | size_t __fwrite(const void* buffer, size_t size, size_t count, FILE* stream); 11 | size_t fwrite(const void* buffer, size_t size, size_t count, FILE* stream); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* MSL_COMMON_SRC_DIRECT_IO_H */ 18 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/extras.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_EXTRAS_H 2 | #define MSL_COMMON_SRC_EXTRAS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int strnicmp(const char* str1, const char* str2, int n); 9 | int stricmp(const char* str1, const char* str2); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* MSL_COMMON_SRC_EXTRAS_H */ 16 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/file_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_FILE_IO_H 2 | #define MSL_COMMON_SRC_FILE_IO_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int __msl_strnicmp(const char* str1, const char* str2, size_t n); 11 | int fflush(FILE* file); 12 | int fclose(FILE* file); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | 18 | #endif /* MSL_COMMON_SRC_FILE_IO_H */ 19 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/float.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_FLOAT_H 2 | #define MSL_COMMON_SRC_FLOAT_H 3 | 4 | #include "fdlibm.h" 5 | 6 | #define FP_SNAN 0 7 | #define FP_QNAN 1 8 | #define FP_INFINITE 2 9 | #define FP_ZERO 3 10 | #define FP_NORMAL 4 11 | #define FP_SUBNORMAL 5 12 | 13 | #define FP_NAN FP_QNAN 14 | 15 | #define fpclassify(x) ((sizeof(x) == sizeof(float)) ? __fpclassifyf(x) : __fpclassifyd(x)) 16 | #define signbit(x) ((sizeof(x) == sizeof(float)) ? __signbitf(x) : __signbitd(x)) 17 | #define isfinite(x) ((fpclassify(x) > 2)) 18 | 19 | #define __signbitf(x) ((*(unsigned char*)&(x)) & 0x80) 20 | 21 | // TODO: OK? 22 | #define __signbitd(x) ((*(unsigned char*)&(x)) & 0x80) 23 | 24 | extern unsigned long __float_nan[]; 25 | extern unsigned long __float_huge[]; 26 | extern unsigned long __float_max[]; 27 | extern unsigned long __float_epsilon[]; 28 | 29 | inline int __fpclassifyf(float __value) { 30 | unsigned long integer = *(unsigned long*)&__value; 31 | 32 | switch (integer & 0x7f800000) { 33 | case 0x7f800000: 34 | if ((integer & 0x7fffff) != 0) { 35 | return FP_QNAN; 36 | } 37 | return FP_INFINITE; 38 | 39 | case 0: 40 | if ((integer & 0x7fffff) != 0) { 41 | return FP_SUBNORMAL; 42 | } 43 | return FP_ZERO; 44 | } 45 | 46 | return FP_NORMAL; 47 | } 48 | 49 | inline int __fpclassifyd(double __value) { 50 | switch (__HI(__value) & 0x7ff00000) { 51 | case 0x7ff00000: { 52 | if ((__HI(__value) & 0x000fffff) || (__LO(__value) & 0xffffffff)) 53 | return FP_QNAN; 54 | else 55 | return FP_INFINITE; 56 | break; 57 | } 58 | case 0: { 59 | if ((__HI(__value) & 0x000fffff) || (__LO(__value) & 0xffffffff)) 60 | return FP_SUBNORMAL; 61 | else 62 | return FP_ZERO; 63 | break; 64 | } 65 | } 66 | return FP_NORMAL; 67 | } 68 | 69 | #endif /* MSL_COMMON_SRC_FLOAT_H */ 70 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/limits: -------------------------------------------------------------------------------- 1 | #ifndef _STD_LIMITS_H 2 | #define _STD_LIMITS_H 3 | 4 | namespace std { 5 | template 6 | class numeric_limits { 7 | public: 8 | inline static T min(); 9 | inline static T max(); 10 | }; 11 | 12 | template <> 13 | class numeric_limits { 14 | public: 15 | inline static char min() { return -0x80; } 16 | inline static char max() { return 0x7F; } 17 | }; 18 | 19 | template <> 20 | class numeric_limits { 21 | public: 22 | inline static short min() { return -0x8000; } 23 | inline static short max() { return 0x7FFF; } 24 | }; 25 | 26 | template <> 27 | class numeric_limits { 28 | public: 29 | inline static int min() { return -0x80000000; } 30 | inline static int max() { return 0x7FFFFFFF; } 31 | }; 32 | 33 | template <> 34 | class numeric_limits { 35 | public: 36 | inline static long min() { return -0x80000000; } 37 | inline static long max() { return 0x7FFFFFFF; } 38 | }; 39 | 40 | template <> 41 | class numeric_limits { 42 | public: 43 | inline static unsigned char min() { return 0x0; } 44 | inline static unsigned char max() { return 0xFF; } 45 | }; 46 | 47 | template <> 48 | class numeric_limits { 49 | public: 50 | inline static unsigned short min() { return 0x0; } 51 | inline static unsigned short max() { return 0xFFFF; } 52 | }; 53 | 54 | template <> 55 | class numeric_limits { 56 | public: 57 | inline static unsigned int min() { return 0x0; } 58 | inline static unsigned int max() { return 0xFFFFFFFF; } 59 | }; 60 | 61 | template <> 62 | class numeric_limits { 63 | public: 64 | inline static unsigned long min() { return 0x0; } 65 | inline static unsigned long max() { return 0xFFFFFFFF; } 66 | }; 67 | 68 | } // namespace std 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/mbstring.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_MBSTRING_H 2 | #define MSL_COMMON_SRC_MBSTRING_H 3 | 4 | #include "MSL_C/MSL_Common/Src/wchar_io.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | size_t wcstombs(char* dst, const wchar_t* src, size_t n); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* MSL_COMMON_SRC_MBSTRING_H */ 17 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/mem.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_MEM_H 2 | #define MSL_COMMON_SRC_MEM_H 3 | 4 | #include "MSL_C/MSL_Common/Src/stddef.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | int memcmp(const void* lhs, const void* rhs, size_t count); 11 | void* __memrchr(const void* ptr, int ch, size_t count); 12 | void* memchr(const void* ptr, int ch, size_t count); 13 | void* memmove(void* dst, const void* src, size_t n); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* MSL_COMMON_SRC_MEM_H */ 20 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/mem_funcs.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_MEM_FUNCS_H 2 | #define MSL_COMMON_SRC_MEM_FUNCS_H 3 | 4 | #include "MSL_C/MSL_Common/Src/stddef.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void __copy_longs_rev_unaligned(void* dst, const void* src, size_t n); 11 | void __copy_longs_unaligned(void* dst, const void* src, size_t n); 12 | void __copy_longs_rev_aligned(void* dst, const void* src, size_t n); 13 | void __copy_longs_aligned(void* dst, const void* src, size_t n); 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* MSL_COMMON_SRC_MEM_FUNCS_H */ 20 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/misc_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_MISC_IO_H 2 | #define MSL_COMMON_SRC_MISC_IO_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void __stdio_atexit(void); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* MSL_COMMON_SRC_MISC_IO_H */ 15 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/printf.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_PRINTF_H 2 | #define MSL_COMMON_SRC_PRINTF_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | #include "Runtime.PPCEABI.H/__va_arg.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | int fprintf(FILE* stream, const char* format, ...); 12 | int printf(const char* format, ...); 13 | int sprintf(const char* str, const char* format, ...); 14 | int snprintf(const char* str, size_t n, const char* format, ...); 15 | int vsnprintf(char* str, size_t n, const char* format, va_list arg); 16 | int vprintf(const char* format, va_list arg); 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif 21 | 22 | #endif /* MSL_COMMON_SRC_PRINTF_H */ 23 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/scanf.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_SCANF_H 2 | #define MSL_COMMON_SRC_SCANF_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int __StringRead(char* str, int ch, int behavior); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* MSL_COMMON_SRC_SCANF_H */ 15 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/signal.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_SIGNAL_H 2 | #define MSL_COMMON_SRC_SIGNAL_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int raise(int sig); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* MSL_COMMON_SRC_SIGNAL_H */ 15 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H_ 2 | #define _STDDEF_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #if defined __INTELLISENSE__ 9 | typedef unsigned int size_t; 10 | typedef int ptrdiff_t; 11 | #else 12 | typedef unsigned long size_t; 13 | typedef long ptrdiff_t; 14 | #endif 15 | 16 | #ifndef NULL 17 | #define NULL (0) 18 | #endif 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | 24 | #endif -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/string.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_STRING_H 2 | #define MSL_COMMON_SRC_STRING_H 3 | 4 | #include "MSL_C/MSL_Common/Src/stddef.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void* memcpy(void* dst, const void* src, size_t n); 11 | void* memset(void* dst, int val, size_t n); 12 | 13 | char* strrchr(const char* str, int c); 14 | char* strchr(const char* str, int c); 15 | int strncmp(const char* str1, const char* str2, size_t n); 16 | int strcmp(const char* str1, const char* str2); 17 | char* strcat(char* dst, const char* src); 18 | char* strncpy(char* dst, const char* src, size_t n); 19 | char* strcpy(char* dst, const char* src); 20 | size_t strlen(const char* str); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* MSL_COMMON_SRC_STRING_H */ 27 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/strtoul.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_STRTOUL_H 2 | #define MSL_COMMON_SRC_STRTOUL_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | long strtol(const char* str, char** endptr, int base); 9 | unsigned long strtoul(const char* str, char** endptr, int base); 10 | unsigned long __strtoul(const char* str, char** endptr, int base); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif /* MSL_COMMON_SRC_STRTOUL_H */ 17 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common/Src/wchar_io.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_SRC_WCHAR_IO_H 2 | #define MSL_COMMON_SRC_WCHAR_IO_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #ifndef __cplusplus 7 | typedef unsigned short wchar_t; 8 | #endif 9 | 10 | int fwide(FILE* file, int mode); 11 | 12 | #endif /* MSL_COMMON_SRC_WCHAR_IO_H */ 13 | -------------------------------------------------------------------------------- /include/MSL_C/MSL_Common_Embedded/Src/ansi_fp.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_COMMON_EMBEDDED_SRC_ANSI_FP_H 2 | #define MSL_COMMON_EMBEDDED_SRC_ANSI_FP_H 3 | 4 | #endif /* MSL_COMMON_EMBEDDED_SRC_ANSI_FP_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_acos.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_ACOS_H 2 | #define MATH_DOUBLE_PRECISION_E_ACOS_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_ACOS_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_asin.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_ASIN_H 2 | #define MATH_DOUBLE_PRECISION_E_ASIN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_ASIN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_atan2.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_ATAN2_H 2 | #define MATH_DOUBLE_PRECISION_E_ATAN2_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_ATAN2_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_exp.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_EXP_H 2 | #define MATH_DOUBLE_PRECISION_E_EXP_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_EXP_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_fmod.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_FMOD_H 2 | #define MATH_DOUBLE_PRECISION_E_FMOD_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_FMOD_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_pow.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_POW_H 2 | #define MATH_DOUBLE_PRECISION_E_POW_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_POW_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_rem_pio2.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_REM_PIO2_H 2 | #define MATH_DOUBLE_PRECISION_E_REM_PIO2_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_REM_PIO2_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/e_sqrt.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_E_SQRT_H 2 | #define MATH_DOUBLE_PRECISION_E_SQRT_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_E_SQRT_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/k_cos.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_K_COS_H 2 | #define MATH_DOUBLE_PRECISION_K_COS_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_K_COS_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/k_rem_pio2.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_K_REM_PIO2_H 2 | #define MATH_DOUBLE_PRECISION_K_REM_PIO2_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_K_REM_PIO2_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/k_sin.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_K_SIN_H 2 | #define MATH_DOUBLE_PRECISION_K_SIN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_K_SIN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/k_tan.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_K_TAN_H 2 | #define MATH_DOUBLE_PRECISION_K_TAN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_K_TAN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_atan.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_ATAN_H 2 | #define MATH_DOUBLE_PRECISION_S_ATAN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_ATAN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_ceil.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_CEIL_H 2 | #define MATH_DOUBLE_PRECISION_S_CEIL_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_CEIL_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_copysign.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_COPYSIGN_H 2 | #define MATH_DOUBLE_PRECISION_S_COPYSIGN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_COPYSIGN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_cos.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_COS_H 2 | #define MATH_DOUBLE_PRECISION_S_COS_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_COS_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_floor.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_FLOOR_H 2 | #define MATH_DOUBLE_PRECISION_S_FLOOR_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_FLOOR_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_frexp.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_FREXP_H 2 | #define MATH_DOUBLE_PRECISION_S_FREXP_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_FREXP_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_ldexp.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_LDEXP_H 2 | #define MATH_DOUBLE_PRECISION_S_LDEXP_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_LDEXP_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_modf.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_MODF_H 2 | #define MATH_DOUBLE_PRECISION_S_MODF_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_MODF_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_sin.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_SIN_H 2 | #define MATH_DOUBLE_PRECISION_S_SIN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_SIN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/s_tan.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_S_TAN_H 2 | #define MATH_DOUBLE_PRECISION_S_TAN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_S_TAN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_acos.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_ACOS_H 2 | #define MATH_DOUBLE_PRECISION_W_ACOS_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_ACOS_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_asin.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_ASIN_H 2 | #define MATH_DOUBLE_PRECISION_W_ASIN_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_ASIN_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_atan2.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_ATAN2_H 2 | #define MATH_DOUBLE_PRECISION_W_ATAN2_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_ATAN2_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_exp.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_EXP_H 2 | #define MATH_DOUBLE_PRECISION_W_EXP_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_EXP_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_fmod.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_FMOD_H 2 | #define MATH_DOUBLE_PRECISION_W_FMOD_H 3 | 4 | double fmod(double, double); 5 | 6 | #endif /* MATH_DOUBLE_PRECISION_W_FMOD_H */ 7 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_pow.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_POW_H 2 | #define MATH_DOUBLE_PRECISION_W_POW_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_POW_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/Math/Double_precision/w_sqrt.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_DOUBLE_PRECISION_W_SQRT_H 2 | #define MATH_DOUBLE_PRECISION_W_SQRT_H 3 | 4 | #endif /* MATH_DOUBLE_PRECISION_W_SQRT_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/PPC_EABI/Src/critical_regions.gamecube.h: -------------------------------------------------------------------------------- 1 | #ifndef PPC_EABI_SRC_CRITICAL_REGIONSGAMECUBE_H 2 | #define PPC_EABI_SRC_CRITICAL_REGIONSGAMECUBE_H 3 | 4 | #endif /* PPC_EABI_SRC_CRITICAL_REGIONSGAMECUBE_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/PPC_EABI/Src/math_ppc.h: -------------------------------------------------------------------------------- 1 | #ifndef PPC_EABI_SRC_MATH_PPC_H 2 | #define PPC_EABI_SRC_MATH_PPC_H 3 | 4 | #endif /* PPC_EABI_SRC_MATH_PPC_H */ 5 | -------------------------------------------------------------------------------- /include/MSL_C/PPC_EABI/Src/uart_console_io_gcn.h: -------------------------------------------------------------------------------- 1 | #ifndef PPC_EABI_SRC_UART_CONSOLE_IO_GCN_H 2 | #define PPC_EABI_SRC_UART_CONSOLE_IO_GCN_H 3 | 4 | #include "MSL_C/MSL_Common/Src/ansi_files.h" 5 | 6 | #endif /* PPC_EABI_SRC_UART_CONSOLE_IO_GCN_H */ 7 | -------------------------------------------------------------------------------- /include/MSL_C/algorithm.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_ALGORITHM_H_ 2 | #define MSL_ALGORITHM_H_ 3 | 4 | namespace std { 5 | template 6 | ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val); 7 | 8 | template 9 | ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& val); 10 | 11 | template 12 | InputIt find_if(InputIt first, InputIt last, UnaryPredicate p); 13 | } // namespace std 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/MSL_C/bitset.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_BITSET_H_ 2 | #define MSL_BITSET_H_ 3 | 4 | namespace std { 5 | template 6 | class bitset { 7 | bitset(); 8 | 9 | void set(size_t pos, bool val); 10 | void reset(size_t pos); 11 | bool test(size_t pos) const; 12 | }; 13 | } // namespace std 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /include/MSL_C/float.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MSL_FLOAT_H_ 3 | #define MSL_FLOAT_H_ 4 | 5 | #include "MSL_C/MSL_Common/Src/float.h" 6 | 7 | #define FLT_MAX (*(float*)__float_max) 8 | #define FLT_EPSILON (*(float*)__float_epsilon) 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /include/MSL_C/functional.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_FUNCTIONAL_H_ 2 | #define MSL_FUNCTIONAL_H_ 3 | 4 | namespace std { 5 | template 6 | struct less {}; 7 | } // namespace std 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/MSL_C/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_MATH_H_ 2 | #define MSL_MATH_H_ 3 | 4 | #include "MSL_C/MSL_Common/Src/float.h" 5 | 6 | #define NAN (*(float*)__float_nan) 7 | #define HUGE_VALF (*(float*)__float_huge) 8 | 9 | #define M_PI 3.14159265358979323846f 10 | 11 | #define DEG_TO_RAD(degrees) (degrees * (M_PI / 180.0f)) 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | int abs(int); 18 | double acos(double); 19 | float acosf(float); 20 | double asin(double); 21 | double atan(double); 22 | double atan2(double, double); 23 | double ceil(double); 24 | double copysign(double, double); 25 | double cos(double); 26 | float cosf(float); 27 | double exp(double); 28 | 29 | extern float __fabsf(float); 30 | inline double fabs(double f) { 31 | return __fabs(f); 32 | } 33 | inline double fabsf2(float f) { 34 | return __fabsf(f); 35 | } 36 | inline float fabsf(float f) { 37 | return fabsf2(f); 38 | } 39 | 40 | double floor(double); 41 | double fmod(double, double); 42 | inline float fmodf(float f1, float f2) { 43 | return fmod(f1, f2); 44 | } 45 | 46 | double frexp(double, int*); 47 | double ldexp(double, int); 48 | double modf(double, double*); 49 | double pow(double, double); 50 | double sin(double); 51 | float sinf(float); 52 | double tan(double); 53 | float tanf(float); 54 | 55 | inline double sqrt_step(double tmpd, float mag) { 56 | return tmpd * 0.5 * (3.0 - mag * (tmpd * tmpd)); 57 | } 58 | 59 | extern inline float sqrtf(float x) { 60 | const double _half = .5; 61 | const double _three = 3.0; 62 | volatile float y; 63 | if (x > 0.0f) { 64 | double guess = __frsqrte((double)x); // returns an approximation to 65 | guess = _half * guess * (_three - guess * guess * x); // now have 12 sig bits 66 | guess = _half * guess * (_three - guess * guess * x); // now have 24 sig bits 67 | guess = _half * guess * (_three - guess * guess * x); // now have 32 sig bits 68 | y = (float)(x * guess); 69 | return y; 70 | } 71 | return x; 72 | } 73 | 74 | extern inline double sqrt(double x) { 75 | if(x > 0.0) 76 | { 77 | double guess = __frsqrte(x); /* returns an approximation to */ 78 | guess = .5*guess*(3.0 - guess*guess*x); /* now have 8 sig bits */ 79 | guess = .5*guess*(3.0 - guess*guess*x); /* now have 16 sig bits */ 80 | guess = .5*guess*(3.0 - guess*guess*x); /* now have 32 sig bits */ 81 | guess = .5*guess*(3.0 - guess*guess*x); /* now have > 53 sig bits */ 82 | return x*guess ; 83 | } 84 | else if ( x == 0 ) 85 | return 0; 86 | else if ( x ) 87 | return NAN; 88 | 89 | return HUGE_VALF; 90 | } 91 | 92 | inline float atan2f(float y, float x) { 93 | return (float)atan2(y, x); 94 | } 95 | 96 | // these are duplicated due to sinf/cosf having a symbol, but 97 | // still being used as inlines elsewhere 98 | inline float i_sinf(float x) { 99 | return sin(x); 100 | } 101 | 102 | inline float i_cosf(float x) { 103 | return cos(x); 104 | } 105 | 106 | #ifdef __cplusplus 107 | }; 108 | #endif 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/MSL_C/stdio.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_STDIO_H_ 2 | #define MSL_STDIO_H_ 3 | 4 | #include "MSL_C/MSL_Common/Src/char_io.h" 5 | #include "MSL_C/MSL_Common/Src/file_io.h" 6 | #include "MSL_C/MSL_Common/Src/printf.h" 7 | 8 | #define stdin (&__files._stdin) 9 | #define stdout (&__files._stdout) 10 | #define stderr (&__files._stderr) 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/MSL_C/stdlib.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_STDLIB_H_ 2 | #define MSL_STDLIB_H_ 3 | 4 | #include "MSL_C/MSL_Common/Src/abort_exit.h" 5 | #include "MSL_C/MSL_Common/Src/arith.h" 6 | #include "MSL_C/MSL_Common/Src/mbstring.h" 7 | #include "MSL_C/MSL_Common/Src/strtoul.h" 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/MSL_C/string.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_STRING_H_ 2 | #define MSL_STRING_H_ 3 | 4 | #include "MSL_C/MSL_Common/Src/extras.h" 5 | #include "MSL_C/MSL_Common/Src/mem.h" 6 | #include "MSL_C/MSL_Common/Src/string.h" 7 | #include "MSL_C/MSL_Common/Src/printf.h" 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /include/MSL_C/utility.h: -------------------------------------------------------------------------------- 1 | #ifndef MSL_UTILITY_H_ 2 | #define MSL_UTILITY_H_ 3 | 4 | namespace std { 5 | template 6 | struct pair { 7 | T1 first; 8 | T2 second; 9 | 10 | pair() { 11 | first = T1(); 12 | second = T2(); 13 | } 14 | }; 15 | } // namespace std 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/Sato/EnStrategy.h: -------------------------------------------------------------------------------- 1 | #ifndef EN_STRATEGY_H 2 | #define EN_STRATEGY_H 3 | 4 | #include "dolphin/types.h" 5 | 6 | class EnemyStrategy; 7 | 8 | class EnStrategyContainer { 9 | u8 mBuffer[0x180]; 10 | EnemyStrategy* mpStrategy; 11 | 12 | public: 13 | EnStrategyContainer(); 14 | virtual ~EnStrategyContainer(); 15 | 16 | virtual s32 getStrategyId(int i_entityIdx) = 0; 17 | 18 | void destroyStrategy(); 19 | EnemyStrategy* createStrategy(int i_entityIdx); 20 | 21 | void* getBuffer() { return mBuffer; } 22 | int getBufferSize() { return 0x180; } 23 | }; 24 | 25 | class EnTsuriStrategies : public EnStrategyContainer { 26 | public: 27 | virtual s32 getStrategyId(int i_entityIdx); 28 | }; 29 | 30 | class EnAttackStrategies : public EnStrategyContainer { 31 | public: 32 | virtual s32 getStrategyId(int i_entityIdx); 33 | }; 34 | 35 | class EnCondStrategies { 36 | u8 mBuffer[0x40]; 37 | EnemyStrategy* mpCondStrategy; 38 | 39 | public: 40 | virtual ~EnCondStrategies(); 41 | 42 | void destroyCondStrategy(); 43 | EnemyStrategy* createCondStrategy(int i_condType); 44 | 45 | s32 getCondStrategyId(int i_entityIdx); 46 | 47 | void* getBuffer() { return mBuffer; } 48 | int getBufferSize() { return 0x40; } 49 | }; 50 | 51 | #endif -------------------------------------------------------------------------------- /include/Sato/EnemyStrategy.h: -------------------------------------------------------------------------------- 1 | #ifndef ENEMY_STRATEGY_H_ 2 | #define ENEMY_STRATEGY_H_ 3 | 4 | #include "dolphin/types.h" 5 | #include "JSystem/JHostIOD/JORServer.h" 6 | 7 | typedef unsigned long size_t; 8 | 9 | typedef void*(*enemyStrategyInitFunc)(void* buf, int bufSize); 10 | enemyStrategyInitFunc* getEnemyStrategyInitFunc(int i_entityIdx); 11 | 12 | class EnemyStrategy : public JORReflexible { 13 | public: 14 | EnemyStrategy(); 15 | virtual ~EnemyStrategy(); 16 | 17 | virtual void init(); 18 | virtual void update(); 19 | virtual s32 unkEnemyStrategyFunc01(); 20 | virtual void unkEnemyStrategyFunc02(); 21 | virtual void doBehavior(); 22 | virtual void doBehaviorInit(); 23 | 24 | void setNextState(s16 i_nextState); 25 | void changeState(); 26 | 27 | static void* operator new(size_t size, void* mem); 28 | static void operator delete(void* mem); 29 | 30 | /* 0x04 */ void* mpZako; 31 | /* 0x08 */ void* mpUserData; 32 | /* 0x0C */ u16 mNextState; 33 | /* 0x0E */ u16 mCurState; 34 | /* 0x10 */ s32 mTimer; 35 | }; 36 | 37 | class EnemyStrategyDecorator : public EnemyStrategy { 38 | public: 39 | EnemyStrategyDecorator(); 40 | 41 | virtual void update(); 42 | s32 setTsuriStrategy(EnemyStrategy* i_tsuriStrategy); 43 | 44 | /* 0x14 */ EnemyStrategy* mpTsuriStrategy; 45 | /* 0x18 */ s16 mTsuriState; 46 | }; 47 | 48 | #endif -------------------------------------------------------------------------------- /include/Sato/EnemyTypicalStrategy.h: -------------------------------------------------------------------------------- 1 | #ifndef ENEMY_TYPICAL_STRATEGY_H 2 | #define ENEMY_TYPICAL_STRATEGY_H 3 | 4 | #include "Sato/EnemyStrategy.h" 5 | #include "Sato/EnStrategy.h" 6 | #include "Koga/CharacterEventObserver.h" 7 | 8 | class EnemyTypicalStrategy : public EnemyStrategyDecorator, public Koga::CharacterEventObserver { 9 | public: 10 | virtual ~EnemyTypicalStrategy() { 11 | 12 | } 13 | 14 | virtual bool onFishingBegin(Koga::CharacterEvent* msg); 15 | 16 | /* 0x20 */ EnTsuriStrategies mTsuriStrategies; 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /include/Sotoike/AITurara.h: -------------------------------------------------------------------------------- 1 | #ifndef AI_TURARA_H 2 | #define AI_TURARA_H 3 | 4 | #include "dolphin/types.h" 5 | #include "Sato/EnemyTypicalStrategy.h" 6 | 7 | class AITurara : public EnemyTypicalStrategy { 8 | public: 9 | AITurara(); 10 | virtual ~AITurara(); 11 | 12 | // EnemyStrategy overrides 13 | virtual s32 unkEnemyStrategyFunc01(); 14 | virtual void doBehavior(); 15 | virtual void doBehaviorInit(); 16 | 17 | // CharacterEventObserver overrides 18 | virtual bool onPlayerLeftRoom(Koga::CharacterEvent* msg); 19 | virtual bool FUN_800ea44c(Koga::CharacterEvent* msg); 20 | 21 | void spawnIcicles(); 22 | 23 | bool procInit_init(); 24 | bool procInit(); 25 | bool procWait_init(); 26 | bool procWait(); 27 | 28 | /* 0x01A8 */ s32 mRespawnTimer; 29 | 30 | /* 0x01AC */ s32 mIcicleCount; 31 | /* 0x01B0 */ s32 mIcicleCharacterIdxs[10]; 32 | 33 | /* 0x01D8 */ u8 mDummy[0x18]; 34 | 35 | /* 0x01F0 */ float mScale; 36 | }; 37 | 38 | #endif -------------------------------------------------------------------------------- /include/Unsorted/IncludeStrategy.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDE_STRATEGY_H_ 2 | #define INCLUDE_STRATEGY_H_ 3 | 4 | #include "dolphin/types.h" 5 | 6 | class EnemyStrategy; 7 | 8 | class IncludeStrategy 9 | { 10 | u8 mStrategyMemory[0x800]; 11 | EnemyStrategy* mpStrategy; 12 | 13 | public: 14 | IncludeStrategy(); 15 | 16 | virtual ~IncludeStrategy(); 17 | virtual void unknownVirtualFunc() = 0; 18 | 19 | void setStrategy(int i_entityIdx); 20 | void destroyStrategy(); 21 | 22 | void* getBuffer() { return mStrategyMemory; } 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/dolphin/types.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPES_H_ 2 | #define TYPES_H_ 3 | 4 | typedef signed char s8; 5 | typedef signed short s16; 6 | typedef signed long s32; 7 | typedef signed long long s64; 8 | typedef unsigned char u8; 9 | typedef unsigned short u16; 10 | typedef unsigned long u32; 11 | typedef unsigned long long u64; 12 | 13 | typedef volatile u8 vu8; 14 | typedef volatile u16 vu16; 15 | typedef volatile u32 vu32; 16 | typedef volatile u64 vu64; 17 | typedef volatile s8 vs8; 18 | typedef volatile s16 vs16; 19 | typedef volatile s32 vs32; 20 | typedef volatile s64 vs64; 21 | 22 | typedef float f32; 23 | typedef double f64; 24 | typedef volatile f32 vf32; 25 | typedef volatile f64 vf64; 26 | 27 | typedef int BOOL; 28 | 29 | #define TRUE 1 30 | #define FALSE 0 31 | 32 | #define READU32_BE(ptr, offset) \ 33 | (((u32)ptr[offset] << 24) | ((u32)ptr[offset + 1] << 16) | ((u32)ptr[offset + 2] << 8) | \ 34 | (u32)ptr[offset + 3]); 35 | 36 | #include "MSL_C/MSL_Common/Src/stddef.h" 37 | 38 | #define INT32_MAX (0x7fffffff) 39 | #define UINT32_MAX (0xffffffff) 40 | 41 | #define FLOAT_MIN (1.175494351e-38f) 42 | #define FLOAT_MAX (3.40282346638528860e+38f) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /orig/GLME01/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sage-of-Mirrors/zmansion/b8692880841e63620fc06eb92ff1b334ecf6576b/orig/GLME01/.gitkeep -------------------------------------------------------------------------------- /src/Koga/CharacterEventObserver.cpp: -------------------------------------------------------------------------------- 1 | #include "Koga/CharacterEventObserver.h" 2 | 3 | // Required for .data to match. 4 | static float dummy[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 5 | 6 | Koga::CharacterEvent::CharacterEvent(const int& message) 7 | { 8 | mMessage = message; 9 | mUnk1 = 0; 10 | mUnk2 = 0; 11 | mUnk3 = 0; 12 | mUnk4 = 0; 13 | mUnk5 = 0; 14 | mUnk6 = 0; 15 | } 16 | 17 | bool Koga::CharacterEventObserver::receiveMessage(CharacterEvent* msg) { 18 | bool bResult; 19 | 20 | switch(msg->mMessage) 21 | { 22 | default: 23 | bResult = false; 24 | break; 25 | case 0: 26 | bResult = true; 27 | break; 28 | case 2: 29 | bResult = onEnteredFlashlightBeam(msg); 30 | break; 31 | case 3: 32 | bResult = onCaptureBegin(msg); 33 | break; 34 | case 4: 35 | bResult = onCaptureEnd(msg); 36 | break; 37 | case 8: 38 | bResult = FUN_800ea380(msg); 39 | break; 40 | case 12: 41 | bResult = onCollideWithPlayer(msg); 42 | break; 43 | case 13: 44 | bResult = onSprayedWithFire(msg); 45 | break; 46 | case 14: 47 | bResult = onSprayedWithIce(msg); 48 | break; 49 | case 15: 50 | bResult = onSprayedWithWater(msg); 51 | break; 52 | case 16: 53 | bResult = onHitWithFireBall(msg); 54 | break; 55 | case 17: 56 | bResult = onHitWithIceBall(msg); 57 | break; 58 | case 18: 59 | bResult = onHitWithWaterBall(msg); 60 | break; 61 | case 9: 62 | bResult = onFishingBegin(msg); 63 | break; 64 | case 10: 65 | bResult = onPlayerLeftRoom(msg); 66 | break; 67 | case 11: 68 | bResult = onPlayerEnteredRoom(msg); 69 | break; 70 | case 19: 71 | bResult = onPlayerTapped(msg); 72 | break; 73 | case 29: 74 | bResult = FUN_800ea44c(msg); 75 | break; 76 | } 77 | 78 | return bResult; 79 | } 80 | 81 | /* Called while the actor is inside the flashlight cone. */ 82 | bool Koga::CharacterEventObserver::onEnteredFlashlightBeam(CharacterEvent* msg) 83 | { 84 | return false; 85 | } 86 | 87 | /* Called when the actor's HP hits 0 while being fished. */ 88 | bool Koga::CharacterEventObserver::onCaptureBegin(CharacterEvent* msg) 89 | { 90 | return false; 91 | } 92 | 93 | /* Called when the actor has been sucked into the Poltergust. */ 94 | bool Koga::CharacterEventObserver::onCaptureEnd(CharacterEvent* msg) 95 | { 96 | return false; 97 | } 98 | 99 | /* TODO: What does this do? */ 100 | bool Koga::CharacterEventObserver::FUN_800ea380(CharacterEvent* msg) 101 | { 102 | return false; 103 | } 104 | 105 | /* Called when the actor collides with the player. */ 106 | bool Koga::CharacterEventObserver::onCollideWithPlayer(CharacterEvent* msg) 107 | { 108 | return false; 109 | } 110 | 111 | /* Called when the actor is exposed to fire. */ 112 | bool Koga::CharacterEventObserver::onSprayedWithFire(CharacterEvent* msg) 113 | { 114 | return false; 115 | } 116 | 117 | /* Called when the actor is exposed to ice. */ 118 | bool Koga::CharacterEventObserver::onSprayedWithIce(CharacterEvent* msg) 119 | { 120 | return false; 121 | } 122 | 123 | /* Called when the actor is exposed to water. */ 124 | bool Koga::CharacterEventObserver::onSprayedWithWater(CharacterEvent* msg) 125 | { 126 | return false; 127 | } 128 | 129 | /* Called when the actor is hit with a fire elemental ball. */ 130 | bool Koga::CharacterEventObserver::onHitWithFireBall(CharacterEvent* msg) 131 | { 132 | return onSprayedWithFire(msg); 133 | } 134 | 135 | /* Called when the actor is hit with an ice elemental ball. */ 136 | bool Koga::CharacterEventObserver::onHitWithIceBall(CharacterEvent* msg) 137 | { 138 | return onSprayedWithIce(msg); 139 | } 140 | 141 | /* Called when the actor is hit with a water elemental ball. */ 142 | bool Koga::CharacterEventObserver::onHitWithWaterBall(CharacterEvent* msg) 143 | { 144 | return onSprayedWithWater(msg); 145 | } 146 | 147 | /* Called when the actor is hooked by the Poltergust. */ 148 | bool Koga::CharacterEventObserver::onFishingBegin(CharacterEvent* msg) 149 | { 150 | return false; 151 | } 152 | 153 | /* Called when the player leaves the actor's current room. */ 154 | bool Koga::CharacterEventObserver::onPlayerLeftRoom(CharacterEvent* msg) 155 | { 156 | return false; 157 | } 158 | 159 | /* Called when the player enters the actor's current room. */ 160 | bool Koga::CharacterEventObserver::onPlayerEnteredRoom(CharacterEvent* msg) 161 | { 162 | return false; 163 | } 164 | 165 | /* Called when the player presses the A button on the actor; treasure chests only? */ 166 | bool Koga::CharacterEventObserver::onPlayerTapped(CharacterEvent* msg) 167 | { 168 | return false; 169 | } 170 | 171 | /* TODO: What does this do? */ 172 | bool Koga::CharacterEventObserver::FUN_800ea44c(CharacterEvent* msg) 173 | { 174 | return false; 175 | } 176 | -------------------------------------------------------------------------------- /src/Sato/EnStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Sato/EnStrategy.h" 2 | #include "Sato/EnemyStrategy.h" 3 | 4 | extern int getTsuriTypeParameter(int i_tsuriType); 5 | extern int getAttackPattern1Parameter(int i_attackType); 6 | 7 | // Required for .data to match. 8 | static float dummy[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 9 | 10 | /* EnStrategyContainer */ 11 | 12 | EnStrategyContainer::EnStrategyContainer() : mpStrategy(NULL) { 13 | 14 | } 15 | 16 | EnStrategyContainer::~EnStrategyContainer() { 17 | destroyStrategy(); 18 | } 19 | 20 | void EnStrategyContainer::destroyStrategy() { 21 | EnemyStrategy* strategy = mpStrategy; 22 | 23 | if (strategy != NULL) { 24 | // This object was initialized via placement new, so we 25 | // can just call its destructor and invalidate its pointer. 26 | strategy->~EnemyStrategy(); 27 | mpStrategy = NULL; 28 | } 29 | } 30 | 31 | EnemyStrategy* EnStrategyContainer::createStrategy(int i_strategyType) { 32 | destroyStrategy(); 33 | 34 | void* buf = getBuffer(); 35 | 36 | enemyStrategyInitFunc* initFunc = getEnemyStrategyInitFunc(getStrategyId(i_strategyType)); 37 | mpStrategy = static_cast((*initFunc)(buf, 0x180)); 38 | 39 | return mpStrategy; 40 | } 41 | 42 | /* EnTsuriStrategies */ 43 | 44 | s32 EnTsuriStrategies::getStrategyId(int i_entityIdx) { 45 | switch (getTsuriTypeParameter(i_entityIdx)) { 46 | default: 47 | return 0x44; 48 | case 1: 49 | return 0x45; 50 | case 2: 51 | return 0x46; 52 | case 3: 53 | return 0x47; 54 | case 4: 55 | return 0x48; 56 | case 5: 57 | return 0x0D; 58 | } 59 | } 60 | 61 | /* EnAttackStrategies */ 62 | s32 EnAttackStrategies::getStrategyId(int i_entityIdx) { 63 | switch(getAttackPattern1Parameter(i_entityIdx)) { 64 | default: 65 | return 0x06; 66 | case 2: 67 | return 0x26; 68 | case 3: 69 | return 0x27; 70 | case 4: 71 | return 0x0C; 72 | case 5: 73 | return 0x37; 74 | case 6: 75 | return 0x07; 76 | case 7: 77 | return 0x0E; 78 | case 8: 79 | return 0x39; 80 | case 9: 81 | return 0x0F; 82 | case 10: 83 | return 0x65; 84 | case 11: 85 | return 0x66; 86 | case 12: 87 | return 0x8F; 88 | case 13: 89 | return 0x95; 90 | case 14: 91 | return 0x98; 92 | case 15: 93 | return 0xB0; 94 | } 95 | } 96 | 97 | /* EnCondStrategies */ 98 | 99 | EnCondStrategies::~EnCondStrategies() { 100 | destroyCondStrategy(); 101 | } 102 | 103 | void EnCondStrategies::destroyCondStrategy() { 104 | EnemyStrategy* strategy = mpCondStrategy; 105 | 106 | if (strategy != NULL) { 107 | // This object was initialized via placement new, so we 108 | // can just call its destructor and invalidate its pointer. 109 | strategy->~EnemyStrategy(); 110 | mpCondStrategy = NULL; 111 | } 112 | } 113 | 114 | EnemyStrategy* EnCondStrategies::createCondStrategy(int i_condType) { 115 | destroyCondStrategy(); 116 | 117 | void* buf = getBuffer(); 118 | 119 | enemyStrategyInitFunc* initFunc = getEnemyStrategyInitFunc(getCondStrategyId(i_condType)); 120 | mpCondStrategy = static_cast((*initFunc)(buf, 0x40)); 121 | 122 | return mpCondStrategy; 123 | } 124 | 125 | s32 EnCondStrategies::getCondStrategyId(int i_entityIdx) { 126 | switch(i_entityIdx) { 127 | case 19: 128 | return 0x7B; 129 | case 1: 130 | return 0x7C; 131 | case 2: 132 | return 0x7D; 133 | case 3: 134 | return 0x7E; 135 | case 4: 136 | return 0x7F; 137 | case 6: 138 | return 0x80; 139 | case 7: 140 | return 0x35; 141 | case 8: 142 | return 0x81; 143 | case 9: 144 | return 0x82; 145 | case 10: 146 | return 0x84; 147 | case 11: 148 | return 0x86; 149 | case 12: 150 | return 0x8E; 151 | case 13: 152 | return 0x90; 153 | case 14: 154 | return 0x91; 155 | case 15: 156 | return 0x96; 157 | case 16: 158 | return 0xA9; 159 | case 17: 160 | return 0xB3; 161 | case 18: 162 | return 0xB4; 163 | default: 164 | return 0x7F; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/Sato/EnemyStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Sato/EnemyStrategy.h" 2 | 3 | // Required for .data to match. 4 | static float dummy[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 5 | 6 | extern enemyStrategyInitFunc gEnemyStrategyInitFuncs[187]; 7 | 8 | enemyStrategyInitFunc* getEnemyStrategyInitFunc(int i_entityIdx) { 9 | return &gEnemyStrategyInitFuncs[i_entityIdx]; 10 | } 11 | 12 | /* EnemyStrategy */ 13 | 14 | EnemyStrategy::EnemyStrategy() { 15 | mpZako = NULL; 16 | mpUserData = NULL; 17 | 18 | mNextState = 0; 19 | mCurState = 0; 20 | mTimer = 0; 21 | } 22 | 23 | EnemyStrategy::~EnemyStrategy() { 24 | 25 | } 26 | 27 | void EnemyStrategy::init() { 28 | 29 | } 30 | 31 | void EnemyStrategy::update() { 32 | if (mNextState != 0xFFFF) { 33 | changeState(); 34 | } 35 | 36 | doBehavior(); 37 | mTimer++; 38 | } 39 | 40 | void EnemyStrategy::doBehavior() { 41 | 42 | } 43 | 44 | void EnemyStrategy::doBehaviorInit() { 45 | 46 | } 47 | 48 | s32 EnemyStrategy::unkEnemyStrategyFunc01() { 49 | return FALSE; 50 | } 51 | 52 | void EnemyStrategy::unkEnemyStrategyFunc02() { 53 | 54 | } 55 | 56 | void EnemyStrategy::setNextState(s16 i_nextState) { 57 | mNextState = i_nextState; 58 | } 59 | 60 | void EnemyStrategy::changeState() { 61 | mCurState = mNextState; 62 | mNextState = 0xFFFF; 63 | mTimer = 0; 64 | 65 | doBehaviorInit(); 66 | } 67 | 68 | void* EnemyStrategy::operator new(size_t size, void* mem) { 69 | return mem; 70 | } 71 | 72 | void EnemyStrategy::operator delete(void* mem) { 73 | 74 | } 75 | 76 | /* EnemyStrategyDecorator */ 77 | 78 | EnemyStrategyDecorator::EnemyStrategyDecorator() { 79 | mpTsuriStrategy = NULL; 80 | mTsuriState = 0x100; 81 | } 82 | 83 | s32 EnemyStrategyDecorator::setTsuriStrategy(EnemyStrategy* i_tsuri) { 84 | if (mpTsuriStrategy != NULL) { 85 | return FALSE; 86 | } 87 | 88 | mpTsuriStrategy = i_tsuri; 89 | return TRUE; 90 | } 91 | 92 | void EnemyStrategyDecorator::update() { 93 | u32 padding[4]; 94 | 95 | if (mpTsuriStrategy == NULL) { 96 | EnemyStrategy::update(); 97 | } 98 | else { 99 | mpTsuriStrategy->update(); 100 | 101 | switch(mpTsuriStrategy->mCurState) { 102 | case 0x100: 103 | case 0x101: 104 | case 0x102: 105 | { 106 | mTsuriState = mpTsuriStrategy->mCurState; 107 | mpTsuriStrategy = NULL; 108 | break; 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Sato/EnemyTypicalStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Sato/EnemyTypicalStrategy.h" 2 | 3 | // Required for .data to match. 4 | static float dummy[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 5 | static float dummy2[] = { 1.0f, 0.95f, 0.9f, 0.85f, 1.0f, 0.9f, 0.75f, 0.3f }; 6 | 7 | bool EnemyTypicalStrategy::onFishingBegin(Koga::CharacterEvent* msg) { 8 | EnemyStrategy* strategy = mTsuriStrategies.createStrategy(0); // TODO: The argument here comes from mpZako->mpCharacter->mEntityIndex. 9 | strategy->mpZako = mpZako; 10 | strategy->mpUserData = mpUserData; 11 | 12 | strategy->setNextState(0); 13 | setTsuriStrategy(strategy); 14 | 15 | return true; 16 | } 17 | -------------------------------------------------------------------------------- /src/Sotoike/AITurara.cpp: -------------------------------------------------------------------------------- 1 | #include "Sotoike/AITurara.h" 2 | 3 | extern void freeCharacterByIndex(int i_idx); 4 | 5 | // Required for .data to match. 6 | static float dummy[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; 7 | static float dummy2[] = { 1.0f, 0.95f, 0.9f, 0.85f, 1.0f, 0.9f, 0.75f, 0.3f }; 8 | 9 | typedef bool(AITurara::*behaviorFunc)(void); 10 | struct AITurara_State { 11 | u16 StateId; 12 | behaviorFunc InitFunc; 13 | behaviorFunc ExecFunc; 14 | }; 15 | 16 | static AITurara_State AITurara_Behaviors[] = { 17 | { 0, &AITurara::procInit_init, &AITurara::procInit }, 18 | { 1, &AITurara::procWait_init, &AITurara::procWait } 19 | }; 20 | 21 | AITurara::AITurara() : mRespawnTimer(0), mScale(1.0f) { 22 | 23 | } 24 | 25 | AITurara::~AITurara() { 26 | for (int i = 0; i < mIcicleCount; i++) { 27 | freeCharacterByIndex(mIcicleCharacterIdxs[i]); 28 | } 29 | } 30 | 31 | void AITurara::doBehaviorInit() { 32 | AITurara_State* state = AITurara_Behaviors; 33 | AITurara_State* end = AITurara_Behaviors + 2; 34 | 35 | AITurara_State* t; 36 | 37 | while (true) { 38 | if (state->StateId == mCurState) { 39 | t = state; 40 | break; 41 | } 42 | 43 | state++; 44 | 45 | if (state == end) { 46 | t = NULL; 47 | break; 48 | } 49 | } 50 | 51 | if (t != NULL) { 52 | (this->*t->InitFunc)(); 53 | } 54 | } 55 | 56 | void AITurara::doBehavior() { 57 | 58 | } 59 | 60 | bool AITurara::FUN_800ea44c(Koga::CharacterEvent* msg) { 61 | msg->mUnknownEntityBools[0xD8] = true; 62 | return true; 63 | } 64 | 65 | s32 AITurara::unkEnemyStrategyFunc01() { 66 | return FALSE; 67 | } 68 | 69 | bool AITurara::onPlayerLeftRoom(Koga::CharacterEvent* msg) { 70 | return true; 71 | } 72 | 73 | void AITurara::spawnIcicles() { 74 | 75 | } 76 | 77 | bool AITurara::procInit_init() { 78 | spawnIcicles(); 79 | setNextState(1); 80 | 81 | return true; 82 | } 83 | 84 | bool AITurara::procInit() { 85 | return true; 86 | } 87 | 88 | bool AITurara::procWait_init() { 89 | 90 | } 91 | 92 | bool AITurara::procWait() { 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/Unsorted/IncludeStrategy.cpp: -------------------------------------------------------------------------------- 1 | #include "Unsorted/IncludeStrategy.h" 2 | #include "Sato/EnemyStrategy.h" 3 | 4 | IncludeStrategy::IncludeStrategy() : mpStrategy(NULL) { 5 | destroyStrategy(); 6 | } 7 | 8 | IncludeStrategy::~IncludeStrategy() { 9 | destroyStrategy(); 10 | } 11 | 12 | void IncludeStrategy::setStrategy(int i_entityIdx) { 13 | destroyStrategy(); 14 | mpStrategy = static_cast((*getEnemyStrategyInitFunc(i_entityIdx))(getBuffer(), 0x800)); 15 | } 16 | 17 | void IncludeStrategy::destroyStrategy() { 18 | EnemyStrategy* strategy = mpStrategy; 19 | 20 | if (strategy != NULL) { 21 | // This object was initialized via placement new, so we 22 | // can just call its destructor and invalidate its pointer. 23 | strategy->~EnemyStrategy(); 24 | mpStrategy = NULL; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Sage-of-Mirrors/zmansion/b8692880841e63620fc06eb92ff1b334ecf6576b/tools/__init__.py -------------------------------------------------------------------------------- /tools/decompctx.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ### 4 | # Generates a ctx.c file, usable for "Context" on https://decomp.me. 5 | # 6 | # Usage: 7 | # python3 tools/decompctx.py src/file.cpp 8 | # 9 | # If changes are made, please submit a PR to 10 | # https://github.com/encounter/dtk-template 11 | ### 12 | 13 | import argparse 14 | import os 15 | import re 16 | 17 | script_dir = os.path.dirname(os.path.realpath(__file__)) 18 | root_dir = os.path.abspath(os.path.join(script_dir, "..")) 19 | src_dir = os.path.join(root_dir, "src") 20 | include_dir = os.path.join(root_dir, "include") 21 | 22 | include_pattern = re.compile(r'^#include\s*[<"](.+?)[>"]$') 23 | guard_pattern = re.compile(r'^#ifndef\s+(.*)$') 24 | 25 | defines = set() 26 | 27 | def import_h_file(in_file: str, r_path: str) -> str: 28 | rel_path = os.path.join(root_dir, r_path, in_file) 29 | inc_path = os.path.join(include_dir, in_file) 30 | if os.path.exists(rel_path): 31 | return import_c_file(rel_path) 32 | elif os.path.exists(inc_path): 33 | return import_c_file(inc_path) 34 | else: 35 | print("Failed to locate", in_file) 36 | exit(1) 37 | 38 | def import_c_file(in_file) -> str: 39 | in_file = os.path.relpath(in_file, root_dir) 40 | out_text = '' 41 | 42 | try: 43 | with open(in_file, encoding="utf-8") as file: 44 | out_text += process_file(in_file, list(file)) 45 | except Exception: 46 | with open(in_file) as file: 47 | out_text += process_file(in_file, list(file)) 48 | return out_text 49 | 50 | def process_file(in_file: str, lines) -> str: 51 | out_text = '' 52 | for idx, line in enumerate(lines): 53 | guard_match = guard_pattern.match(line.strip()) 54 | if idx == 0: 55 | if guard_match: 56 | if guard_match[1] in defines: 57 | break 58 | defines.add(guard_match[1]) 59 | print("Processing file", in_file) 60 | include_match = include_pattern.match(line.strip()) 61 | if include_match and not include_match[1].endswith(".s"): 62 | out_text += f"/* \"{in_file}\" line {idx} \"{include_match[1]}\" */\n" 63 | out_text += import_h_file(include_match[1], os.path.dirname(in_file)) 64 | out_text += f"/* end \"{include_match[1]}\" */\n" 65 | else: 66 | out_text += line 67 | 68 | return out_text 69 | 70 | def main(): 71 | parser = argparse.ArgumentParser( 72 | description="""Create a context file which can be used for decomp.me""" 73 | ) 74 | parser.add_argument( 75 | "c_file", 76 | help="""File from which to create context""", 77 | ) 78 | args = parser.parse_args() 79 | 80 | output = import_c_file(args.c_file) 81 | 82 | with open(os.path.join(root_dir, "ctx.c"), "w", encoding="utf-8") as f: 83 | f.write(output) 84 | 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /tools/download_tool.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ### 4 | # Downloads various tools from GitHub releases. 5 | # 6 | # Usage: 7 | # python3 tools/download_tool.py wibo build/tools/wibo --tag 1.0.0 8 | # 9 | # If changes are made, please submit a PR to 10 | # https://github.com/encounter/dtk-template 11 | ### 12 | 13 | import argparse 14 | import io 15 | import os 16 | import platform 17 | import shutil 18 | import stat 19 | import sys 20 | import urllib.request 21 | import zipfile 22 | 23 | from pathlib import Path 24 | 25 | 26 | def dtk_url(tag): 27 | uname = platform.uname() 28 | suffix = "" 29 | system = uname.system.lower() 30 | if system == "darwin": 31 | system = "macos" 32 | elif system == "windows": 33 | suffix = ".exe" 34 | arch = uname.machine.lower() 35 | if arch == "amd64": 36 | arch = "x86_64" 37 | 38 | repo = "https://github.com/encounter/decomp-toolkit" 39 | return f"{repo}/releases/download/{tag}/dtk-{system}-{arch}{suffix}" 40 | 41 | 42 | def sjiswrap_url(tag): 43 | repo = "https://github.com/encounter/sjiswrap" 44 | return f"{repo}/releases/download/{tag}/sjiswrap-windows-x86.exe" 45 | 46 | 47 | def wibo_url(tag): 48 | repo = "https://github.com/decompals/wibo" 49 | return f"{repo}/releases/download/{tag}/wibo" 50 | 51 | 52 | def compilers_url(tag): 53 | return f"https://files.decomp.dev/compilers_{tag}.zip" 54 | 55 | 56 | TOOLS = { 57 | "dtk": dtk_url, 58 | "sjiswrap": sjiswrap_url, 59 | "wibo": wibo_url, 60 | "compilers": compilers_url, 61 | } 62 | 63 | 64 | def main(): 65 | parser = argparse.ArgumentParser() 66 | parser.add_argument("tool", help="Tool name") 67 | parser.add_argument("output", type=Path, help="output file path") 68 | parser.add_argument("--tag", help="GitHub tag", required=True) 69 | args = parser.parse_args() 70 | 71 | url = TOOLS[args.tool](args.tag) 72 | output = Path(args.output) 73 | 74 | print(f"Downloading {url} to {output}") 75 | req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) 76 | with urllib.request.urlopen(req) as response: 77 | if url.endswith(".zip"): 78 | data = io.BytesIO(response.read()) 79 | with zipfile.ZipFile(data) as f: 80 | f.extractall(output) 81 | output.touch(mode=0o755) 82 | else: 83 | with open(output, "wb") as f: 84 | shutil.copyfileobj(response, f) 85 | st = os.stat(output) 86 | os.chmod(output, st.st_mode | stat.S_IEXEC) 87 | 88 | 89 | if __name__ == "__main__": 90 | main() 91 | -------------------------------------------------------------------------------- /tools/ninja_syntax.py: -------------------------------------------------------------------------------- 1 | # Copyright 2011 Google Inc. All Rights Reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | """Python module for generating .ninja files. 16 | 17 | Note that this is emphatically not a required piece of Ninja; it's 18 | just a helpful utility for build-file-generation systems that already 19 | use Python. 20 | """ 21 | 22 | import re 23 | import textwrap 24 | 25 | 26 | def escape_path(word): 27 | return word.replace("$ ", "$$ ").replace(" ", "$ ").replace(":", "$:") 28 | 29 | 30 | class Writer(object): 31 | def __init__(self, output, width=78): 32 | self.output = output 33 | self.width = width 34 | 35 | def newline(self): 36 | self.output.write("\n") 37 | 38 | def comment(self, text): 39 | for line in textwrap.wrap( 40 | text, self.width - 2, break_long_words=False, break_on_hyphens=False 41 | ): 42 | self.output.write("# " + line + "\n") 43 | 44 | def variable(self, key, value, indent=0): 45 | if value is None: 46 | return 47 | if isinstance(value, list): 48 | value = " ".join(filter(None, value)) # Filter out empty strings. 49 | self._line("%s = %s" % (key, value), indent) 50 | 51 | def pool(self, name, depth): 52 | self._line("pool %s" % name) 53 | self.variable("depth", depth, indent=1) 54 | 55 | def rule( 56 | self, 57 | name, 58 | command, 59 | description=None, 60 | depfile=None, 61 | generator=False, 62 | pool=None, 63 | restat=False, 64 | rspfile=None, 65 | rspfile_content=None, 66 | deps=None, 67 | ): 68 | self._line("rule %s" % name) 69 | self.variable("command", command, indent=1) 70 | if description: 71 | self.variable("description", description, indent=1) 72 | if depfile: 73 | self.variable("depfile", depfile, indent=1) 74 | if generator: 75 | self.variable("generator", "1", indent=1) 76 | if pool: 77 | self.variable("pool", pool, indent=1) 78 | if restat: 79 | self.variable("restat", "1", indent=1) 80 | if rspfile: 81 | self.variable("rspfile", rspfile, indent=1) 82 | if rspfile_content: 83 | self.variable("rspfile_content", rspfile_content, indent=1) 84 | if deps: 85 | self.variable("deps", deps, indent=1) 86 | 87 | def build( 88 | self, 89 | outputs, 90 | rule, 91 | inputs=None, 92 | implicit=None, 93 | order_only=None, 94 | variables=None, 95 | implicit_outputs=None, 96 | pool=None, 97 | dyndep=None, 98 | ): 99 | outputs = as_list(outputs) 100 | out_outputs = [escape_path(x) for x in outputs] 101 | all_inputs = [escape_path(x) for x in as_list(inputs)] 102 | 103 | if implicit: 104 | implicit = [escape_path(x) for x in as_list(implicit)] 105 | all_inputs.append("|") 106 | all_inputs.extend(implicit) 107 | if order_only: 108 | order_only = [escape_path(x) for x in as_list(order_only)] 109 | all_inputs.append("||") 110 | all_inputs.extend(order_only) 111 | if implicit_outputs: 112 | implicit_outputs = [escape_path(x) for x in as_list(implicit_outputs)] 113 | out_outputs.append("|") 114 | out_outputs.extend(implicit_outputs) 115 | 116 | self._line( 117 | "build %s: %s" % (" ".join(out_outputs), " ".join([rule] + all_inputs)) 118 | ) 119 | if pool is not None: 120 | self._line(" pool = %s" % pool) 121 | if dyndep is not None: 122 | self._line(" dyndep = %s" % dyndep) 123 | 124 | if variables: 125 | if isinstance(variables, dict): 126 | iterator = iter(variables.items()) 127 | else: 128 | iterator = iter(variables) 129 | 130 | for key, val in iterator: 131 | self.variable(key, val, indent=1) 132 | 133 | return outputs 134 | 135 | def include(self, path): 136 | self._line("include %s" % path) 137 | 138 | def subninja(self, path): 139 | self._line("subninja %s" % path) 140 | 141 | def default(self, paths): 142 | self._line("default %s" % " ".join(as_list(paths))) 143 | 144 | def _count_dollars_before_index(self, s, i): 145 | """Returns the number of '$' characters right in front of s[i].""" 146 | dollar_count = 0 147 | dollar_index = i - 1 148 | while dollar_index > 0 and s[dollar_index] == "$": 149 | dollar_count += 1 150 | dollar_index -= 1 151 | return dollar_count 152 | 153 | def _line(self, text, indent=0): 154 | """Write 'text' word-wrapped at self.width characters.""" 155 | leading_space = " " * indent 156 | while len(leading_space) + len(text) > self.width: 157 | # The text is too wide; wrap if possible. 158 | 159 | # Find the rightmost space that would obey our width constraint and 160 | # that's not an escaped space. 161 | available_space = self.width - len(leading_space) - len(" $") 162 | space = available_space 163 | while True: 164 | space = text.rfind(" ", 0, space) 165 | if space < 0 or self._count_dollars_before_index(text, space) % 2 == 0: 166 | break 167 | 168 | if space < 0: 169 | # No such space; just use the first unescaped space we can find. 170 | space = available_space - 1 171 | while True: 172 | space = text.find(" ", space + 1) 173 | if ( 174 | space < 0 175 | or self._count_dollars_before_index(text, space) % 2 == 0 176 | ): 177 | break 178 | if space < 0: 179 | # Give up on breaking. 180 | break 181 | 182 | self.output.write(leading_space + text[0:space] + " $\n") 183 | text = text[space + 1 :] 184 | 185 | # Subsequent lines are continuations, so indent them. 186 | leading_space = " " * (indent + 2) 187 | 188 | self.output.write(leading_space + text + "\n") 189 | 190 | def close(self): 191 | self.output.close() 192 | 193 | 194 | def as_list(input): 195 | if input is None: 196 | return [] 197 | if isinstance(input, list): 198 | return input 199 | return [input] 200 | 201 | 202 | def escape(string): 203 | """Escape a string such that it can be embedded into a Ninja file without 204 | further interpretation.""" 205 | assert "\n" not in string, "Ninja syntax does not allow newlines" 206 | # We only have one special metacharacter: '$'. 207 | return string.replace("$", "$$") 208 | 209 | 210 | def expand(string, vars, local_vars={}): 211 | """Expand a string containing $vars as Ninja would. 212 | 213 | Note: doesn't handle the full Ninja variable syntax, but it's enough 214 | to make configure.py's use of it work. 215 | """ 216 | 217 | def exp(m): 218 | var = m.group(1) 219 | if var == "$": 220 | return "$" 221 | return local_vars.get(var, vars.get(var, "")) 222 | 223 | return re.sub(r"\$(\$|\w*)", exp, string) 224 | -------------------------------------------------------------------------------- /tools/project.py: -------------------------------------------------------------------------------- 1 | ### 2 | # decomp-toolkit project generator 3 | # Generates build.ninja and objdiff.json. 4 | # 5 | # This generator is intentionally project-agnostic 6 | # and shared between multiple projects. Any configuration 7 | # specific to a project should be added to `configure.py`. 8 | # 9 | # If changes are made, please submit a PR to 10 | # https://github.com/encounter/dtk-template 11 | ### 12 | 13 | import io 14 | import json 15 | import os 16 | import platform 17 | import sys 18 | 19 | from pathlib import Path 20 | from . import ninja_syntax 21 | 22 | if sys.platform == "cygwin": 23 | sys.exit( 24 | f"Cygwin/MSYS2 is not supported." 25 | f"\nPlease use native Windows Python instead." 26 | f"\n(Current path: {sys.executable})" 27 | ) 28 | 29 | 30 | class ProjectConfig: 31 | def __init__(self): 32 | # Paths 33 | self.build_dir = Path("build") 34 | self.src_dir = Path("src") 35 | self.tools_dir = Path("tools") 36 | 37 | # Tooling 38 | self.dtk_tag = None # Git tag 39 | self.build_dtk_path = None # If None, download 40 | self.compilers_tag = None # 1 41 | self.compilers_path = None # If None, download 42 | self.wibo_tag = None # Git tag 43 | self.wrapper = None # If None, download wibo on Linux 44 | self.sjiswrap_tag = None # Git tag 45 | self.sjiswrap_path = None # If None, download 46 | 47 | # Project config 48 | self.build_rels = True # Build REL files 49 | self.check_sha_path = None # Path to version.sha1 50 | self.config_path = None # Path to config.yml 51 | self.debug = False # Build with debug info 52 | self.generate_map = False # Generate map file(s) 53 | self.ldflags = None # Linker flags 54 | self.libs = None # List of libraries 55 | self.linker_version = None # mwld version 56 | self.version = None # Version name 57 | self.warn_missing_config = False # Warn on missing unit configuration 58 | self.warn_missing_source = False # Warn on missing source file 59 | 60 | # Progress output and progress.json config 61 | self.progress_all = True # Include combined "all" category 62 | self.progress_modules = True # Include combined "modules" category 63 | self.progress_each_module = True # Include individual modules, disable for large numbers of modules 64 | 65 | def validate(self): 66 | required_attrs = [ 67 | "build_dir", 68 | "src_dir", 69 | "tools_dir", 70 | "check_sha_path", 71 | "config_path", 72 | "ldflags", 73 | "linker_version", 74 | "libs", 75 | "version", 76 | ] 77 | for attr in required_attrs: 78 | if getattr(self, attr) is None: 79 | sys.exit(f"ProjectConfig.{attr} missing") 80 | 81 | def find_object(self, name): 82 | for lib in self.libs: 83 | for obj in lib["objects"]: 84 | if obj.name == name: 85 | return [lib, obj] 86 | return None 87 | 88 | def out_path(self): 89 | return self.build_dir / self.version 90 | 91 | 92 | class Object: 93 | def __init__(self, completed, name, **options): 94 | self.name = name 95 | self.completed = completed 96 | self.options = { 97 | "add_to_all": True, 98 | "cflags": None, 99 | "extra_cflags": None, 100 | "mw_version": None, 101 | "shiftjis": True, 102 | "source": name, 103 | } 104 | self.options.update(options) 105 | 106 | 107 | def is_windows(): 108 | return os.name == "nt" 109 | 110 | 111 | # On Windows, we need this to use && in commands 112 | CHAIN = "cmd /c " if is_windows() else "" 113 | # Native executable extension 114 | EXE = ".exe" if is_windows() else "" 115 | 116 | 117 | # Replace forward slashes with backslashes on Windows 118 | def os_str(value): 119 | return str(value).replace("/", os.sep) 120 | 121 | 122 | # Replace backslashes with forward slashes on Windows 123 | def unix_str(value): 124 | return str(value).replace(os.sep, "/") 125 | 126 | 127 | # Stringify paths for ninja_syntax 128 | def path(value): 129 | if value is None: 130 | return None 131 | elif isinstance(value, list): 132 | return list(map(os_str, filter(lambda x: x is not None, value))) 133 | else: 134 | return [os_str(value)] 135 | 136 | 137 | # Load decomp-toolkit generated config.json 138 | def load_build_config(config, build_config_path): 139 | if not build_config_path.is_file(): 140 | return None 141 | 142 | def versiontuple(v): 143 | return tuple(map(int, (v.split(".")))) 144 | 145 | f = open(build_config_path, "r", encoding="utf-8") 146 | build_config = json.load(f) 147 | config_version = build_config.get("version") 148 | if not config_version: 149 | # Invalid config.json 150 | f.close() 151 | os.remove(build_config_path) 152 | return None 153 | 154 | dtk_version = config.dtk_tag[1:] # Strip v 155 | if versiontuple(config_version) < versiontuple(dtk_version): 156 | # Outdated config.json 157 | f.close() 158 | os.remove(build_config_path) 159 | return None 160 | 161 | f.close() 162 | return build_config 163 | 164 | 165 | # Generate build.ninja and objdiff.json 166 | def generate_build(config): 167 | build_config = load_build_config(config, config.out_path() / "config.json") 168 | generate_build_ninja(config, build_config) 169 | generate_objdiff_config(config, build_config) 170 | 171 | 172 | # Generate build.ninja 173 | def generate_build_ninja(config, build_config): 174 | config.validate() 175 | 176 | out = io.StringIO() 177 | n = ninja_syntax.Writer(out) 178 | n.variable("ninja_required_version", "1.3") 179 | n.newline() 180 | 181 | configure_script = os.path.relpath(os.path.abspath(sys.argv[0])) 182 | python_lib = os.path.relpath(__file__) 183 | python_lib_dir = os.path.dirname(python_lib) 184 | n.comment("The arguments passed to configure.py, for rerunning it.") 185 | n.variable("configure_args", sys.argv[1:]) 186 | n.variable("python", f'"{sys.executable}"') 187 | n.newline() 188 | 189 | ### 190 | # Variables 191 | ### 192 | n.comment("Variables") 193 | ldflags = " ".join(config.ldflags) 194 | if config.generate_map: 195 | ldflags += " -mapunused" 196 | if config.debug: 197 | ldflags += " -g" 198 | n.variable("ldflags", ldflags) 199 | n.variable("mw_version", config.linker_version) 200 | n.newline() 201 | 202 | ### 203 | # Tooling 204 | ### 205 | n.comment("Tooling") 206 | 207 | build_path = config.out_path() 208 | build_tools_path = config.build_dir / "tools" 209 | download_tool = config.tools_dir / "download_tool.py" 210 | n.rule( 211 | name="download_tool", 212 | command=f"$python {download_tool} $tool $out --tag $tag", 213 | description="TOOL $out", 214 | ) 215 | 216 | if config.build_dtk_path: 217 | dtk = build_tools_path / "release" / f"dtk{EXE}" 218 | n.rule( 219 | name="cargo", 220 | command="cargo build --release --manifest-path $in --bin $bin --target-dir $target", 221 | description="CARGO $bin", 222 | depfile=path(Path("$target") / "release" / "$bin.d"), 223 | deps="gcc", 224 | ) 225 | n.build( 226 | outputs=path(dtk), 227 | rule="cargo", 228 | inputs=path(config.build_dtk_path / "Cargo.toml"), 229 | implicit=path(config.build_dtk_path / "Cargo.lock"), 230 | variables={ 231 | "bin": "dtk", 232 | "target": build_tools_path, 233 | }, 234 | ) 235 | elif config.dtk_tag: 236 | dtk = build_tools_path / f"dtk{EXE}" 237 | n.build( 238 | outputs=path(dtk), 239 | rule="download_tool", 240 | implicit=path(download_tool), 241 | variables={ 242 | "tool": "dtk", 243 | "tag": config.dtk_tag, 244 | }, 245 | ) 246 | else: 247 | sys.exit("ProjectConfig.dtk_tag missing") 248 | 249 | if config.sjiswrap_path: 250 | sjiswrap = config.sjiswrap_path 251 | elif config.sjiswrap_tag: 252 | sjiswrap = build_tools_path / "sjiswrap.exe" 253 | n.build( 254 | outputs=path(sjiswrap), 255 | rule="download_tool", 256 | implicit=path(download_tool), 257 | variables={ 258 | "tool": "sjiswrap", 259 | "tag": config.sjiswrap_tag, 260 | }, 261 | ) 262 | else: 263 | sys.exit("ProjectConfig.sjiswrap_tag missing") 264 | 265 | # Only add an implicit dependency on wibo if we download it 266 | wrapper = config.wrapper 267 | wrapper_implicit = None 268 | if ( 269 | config.wibo_tag is not None 270 | and sys.platform == "linux" 271 | and platform.machine() in ("i386", "x86_64") 272 | and config.wrapper is None 273 | ): 274 | wrapper = build_tools_path / "wibo" 275 | wrapper_implicit = wrapper 276 | n.build( 277 | outputs=path(wrapper), 278 | rule="download_tool", 279 | implicit=path(download_tool), 280 | variables={ 281 | "tool": "wibo", 282 | "tag": config.wibo_tag, 283 | }, 284 | ) 285 | if not is_windows() and wrapper is None: 286 | wrapper = "wine" 287 | wrapper_cmd = f"{wrapper} " if wrapper else "" 288 | 289 | compilers_implicit = None 290 | if config.compilers_path: 291 | compilers = config.compilers_path 292 | elif config.compilers_tag: 293 | compilers = config.build_dir / "compilers" 294 | compilers_implicit = compilers 295 | n.build( 296 | outputs=path(compilers), 297 | rule="download_tool", 298 | implicit=path(download_tool), 299 | variables={ 300 | "tool": "compilers", 301 | "tag": config.compilers_tag, 302 | }, 303 | ) 304 | 305 | n.newline() 306 | 307 | ### 308 | # Build rules 309 | ### 310 | compiler_path = compilers / "$mw_version" 311 | 312 | # MWCC 313 | mwcc = compiler_path / "mwcceppc.exe" 314 | mwcc_cmd = f"{wrapper_cmd}{mwcc} $cflags -MMD -c $in -o $basedir" 315 | mwcc_implicit = [compilers_implicit or mwcc, wrapper_implicit] 316 | 317 | # MWCC with UTF-8 to Shift JIS wrapper 318 | mwcc_sjis_cmd = f"{wrapper_cmd}{sjiswrap} {mwcc} $cflags -MMD -c $in -o $basedir" 319 | mwcc_sjis_implicit = [*mwcc_implicit, sjiswrap] 320 | 321 | # MWLD 322 | mwld = compiler_path / "mwldeppc.exe" 323 | mwld_cmd = f"{wrapper_cmd}{mwld} $ldflags -o $out @$out.rsp" 324 | mwld_implicit = [compilers_implicit or mwld, wrapper_implicit] 325 | 326 | if os.name != "nt": 327 | transform_dep = config.tools_dir / "transform_dep.py" 328 | mwcc_cmd += f" && $python {transform_dep} $basefile.d $basefile.d" 329 | mwcc_sjis_cmd += f" && $python {transform_dep} $basefile.d $basefile.d" 330 | mwcc_implicit.append(transform_dep) 331 | mwcc_sjis_implicit.append(transform_dep) 332 | 333 | n.comment("Link ELF file") 334 | n.rule( 335 | name="link", 336 | command=mwld_cmd, 337 | description="LINK $out", 338 | rspfile="$out.rsp", 339 | rspfile_content="$in_newline", 340 | ) 341 | n.newline() 342 | 343 | n.comment("Generate DOL") 344 | n.rule( 345 | name="elf2dol", 346 | command=f"{dtk} elf2dol $in $out", 347 | description="DOL $out", 348 | ) 349 | n.newline() 350 | 351 | n.comment("Generate REL(s)") 352 | makerel_rsp = build_path / "makerel.rsp" 353 | n.rule( 354 | name="makerel", 355 | command=f"{dtk} rel make -w -c $config @{makerel_rsp}", 356 | description="REL", 357 | rspfile=path(makerel_rsp), 358 | rspfile_content="$in_newline", 359 | ) 360 | n.newline() 361 | 362 | n.comment("MWCC build") 363 | n.rule( 364 | name="mwcc", 365 | command=mwcc_cmd, 366 | description="MWCC $out", 367 | depfile="$basefile.d", 368 | deps="gcc", 369 | ) 370 | n.newline() 371 | 372 | n.comment("MWCC build (with UTF-8 to Shift JIS wrapper)") 373 | n.rule( 374 | name="mwcc_sjis", 375 | command=mwcc_sjis_cmd, 376 | description="MWCC $out", 377 | depfile="$basefile.d", 378 | deps="gcc", 379 | ) 380 | n.newline() 381 | 382 | n.comment("Host build") 383 | n.variable("host_cflags", "-I include -Wno-trigraphs") 384 | n.variable( 385 | "host_cppflags", 386 | "-std=c++98 -I include -fno-exceptions -fno-rtti -D_CRT_SECURE_NO_WARNINGS -Wno-trigraphs -Wno-c++11-extensions", 387 | ) 388 | n.rule( 389 | name="host_cc", 390 | command="clang $host_cflags -c -o $out $in", 391 | description="CC $out", 392 | ) 393 | n.rule( 394 | name="host_cpp", 395 | command="clang++ $host_cppflags -c -o $out $in", 396 | description="CXX $out", 397 | ) 398 | n.newline() 399 | 400 | ### 401 | # Source files 402 | ### 403 | n.comment("Source files") 404 | build_src_path = build_path / "src" 405 | build_host_path = build_path / "host" 406 | build_config_path = build_path / "config.json" 407 | 408 | def map_path(path): 409 | return path.parent / (path.name + ".MAP") 410 | 411 | class LinkStep: 412 | def __init__(self, config): 413 | self.name = config["name"] 414 | self.module_id = config["module_id"] 415 | self.ldscript = config["ldscript"] 416 | self.entry = config["entry"] 417 | self.inputs = [] 418 | 419 | def add(self, obj): 420 | self.inputs.append(obj) 421 | 422 | def output(self): 423 | if self.module_id == 0: 424 | return build_path / f"{self.name}.dol" 425 | else: 426 | return build_path / self.name / f"{self.name}.rel" 427 | 428 | def partial_output(self): 429 | if self.module_id == 0: 430 | return build_path / f"{self.name}.elf" 431 | else: 432 | return build_path / self.name / f"{self.name}.plf" 433 | 434 | def write(self, n): 435 | n.comment(f"Link {self.name}") 436 | if self.module_id == 0: 437 | elf_path = build_path / f"{self.name}.elf" 438 | dol_path = build_path / f"{self.name}.dol" 439 | elf_ldflags = f"$ldflags -lcf {self.ldscript}" 440 | if config.generate_map: 441 | elf_map = map_path(elf_path) 442 | elf_ldflags += f" -map {elf_map}" 443 | else: 444 | elf_map = None 445 | n.build( 446 | outputs=path(elf_path), 447 | rule="link", 448 | inputs=path(self.inputs), 449 | implicit=path([self.ldscript, *mwld_implicit]), 450 | implicit_outputs=path(elf_map), 451 | variables={"ldflags": elf_ldflags}, 452 | ) 453 | n.build( 454 | outputs=path(dol_path), 455 | rule="elf2dol", 456 | inputs=path(elf_path), 457 | implicit=path(dtk), 458 | ) 459 | else: 460 | preplf_path = build_path / self.name / f"{self.name}.preplf" 461 | plf_path = build_path / self.name / f"{self.name}.plf" 462 | preplf_ldflags = f"$ldflags -sdata 0 -sdata2 0 -r" 463 | plf_ldflags = f"$ldflags -sdata 0 -sdata2 0 -m {self.entry} -r1 -strip_partial -lcf {self.ldscript}" 464 | if config.generate_map: 465 | preplf_map = map_path(preplf_path) 466 | preplf_ldflags += f" -map {preplf_map}" 467 | plf_map = map_path(plf_path) 468 | plf_ldflags += f" -map {plf_map}" 469 | else: 470 | preplf_map = None 471 | plf_map = None 472 | n.build( 473 | outputs=path(preplf_path), 474 | rule="link", 475 | inputs=path(self.inputs), 476 | implicit=path(mwld_implicit), 477 | implicit_outputs=path(preplf_map), 478 | variables={"ldflags": preplf_ldflags}, 479 | ) 480 | n.build( 481 | outputs=path(plf_path), 482 | rule="link", 483 | inputs=path(self.inputs), 484 | implicit=path([self.ldscript, preplf_path, *mwld_implicit]), 485 | implicit_outputs=path(plf_map), 486 | variables={"ldflags": plf_ldflags}, 487 | ) 488 | n.newline() 489 | 490 | if build_config: 491 | link_steps = [] 492 | used_compiler_versions = set() 493 | source_inputs = [] 494 | host_source_inputs = [] 495 | source_added = set() 496 | 497 | def make_cflags_str(cflags): 498 | if isinstance(cflags, list): 499 | return " ".join(cflags) 500 | else: 501 | return cflags 502 | 503 | def add_unit(build_obj, link_step): 504 | obj_path, obj_name = build_obj["object"], build_obj["name"] 505 | result = config.find_object(obj_name) 506 | if not result: 507 | if config.warn_missing_config and not build_obj["autogenerated"]: 508 | print(f"Missing configuration for {obj_name}") 509 | link_step.add(obj_path) 510 | return 511 | 512 | lib, obj = result 513 | lib_name = lib["lib"] 514 | 515 | options = obj.options 516 | completed = obj.completed 517 | 518 | unit_src_path = config.src_dir / options["source"] 519 | if not unit_src_path.exists(): 520 | if config.warn_missing_source or completed: 521 | print(f"Missing source file {unit_src_path}") 522 | link_step.add(obj_path) 523 | return 524 | 525 | mw_version = options["mw_version"] or lib["mw_version"] 526 | cflags_str = make_cflags_str(options["cflags"] or lib["cflags"]) 527 | if options["extra_cflags"] is not None: 528 | extra_cflags_str = make_cflags_str(options["extra_cflags"]) 529 | cflags_str += " " + extra_cflags_str 530 | used_compiler_versions.add(mw_version) 531 | 532 | base_object = Path(obj.name).with_suffix("") 533 | src_obj_path = build_src_path / f"{base_object}.o" 534 | src_base_path = build_src_path / base_object 535 | 536 | if src_obj_path not in source_added: 537 | source_added.add(src_obj_path) 538 | 539 | n.comment(f"{obj_name}: {lib_name} (linked {completed})") 540 | n.build( 541 | outputs=path(src_obj_path), 542 | rule="mwcc_sjis" if options["shiftjis"] else "mwcc", 543 | inputs=path(unit_src_path), 544 | variables={ 545 | "mw_version": path(Path(mw_version)), 546 | "cflags": cflags_str, 547 | "basedir": os.path.dirname(src_base_path), 548 | "basefile": path(src_base_path), 549 | }, 550 | implicit=path( 551 | mwcc_sjis_implicit if options["shiftjis"] else mwcc_implicit 552 | ), 553 | ) 554 | 555 | if lib.get("host", False): 556 | host_obj_path = build_host_path / f"{base_object}.o" 557 | host_base_path = build_host_path / base_object 558 | n.build( 559 | outputs=path(host_obj_path), 560 | rule="host_cc" if unit_src_path.suffix == ".c" else "host_cpp", 561 | inputs=path(unit_src_path), 562 | variables={ 563 | "basedir": os.path.dirname(host_base_path), 564 | "basefile": path(host_base_path), 565 | }, 566 | ) 567 | if options["add_to_all"]: 568 | host_source_inputs.append(host_obj_path) 569 | n.newline() 570 | 571 | if options["add_to_all"]: 572 | source_inputs.append(src_obj_path) 573 | 574 | if completed: 575 | obj_path = src_obj_path 576 | link_step.add(obj_path) 577 | 578 | # Add DOL link step 579 | link_step = LinkStep(build_config) 580 | for unit in build_config["units"]: 581 | add_unit(unit, link_step) 582 | link_steps.append(link_step) 583 | 584 | if config.build_rels: 585 | # Add REL link steps 586 | for module in build_config["modules"]: 587 | module_link_step = LinkStep(module) 588 | for unit in module["units"]: 589 | add_unit(unit, module_link_step) 590 | link_steps.append(module_link_step) 591 | n.newline() 592 | 593 | # Check if all compiler versions exist 594 | for mw_version in used_compiler_versions: 595 | mw_path = compilers / mw_version / "mwcceppc.exe" 596 | if config.compilers_path and not os.path.exists(mw_path): 597 | sys.exit(f"Compiler {mw_path} does not exist") 598 | 599 | # Check if linker exists 600 | mw_path = compilers / config.linker_version / "mwldeppc.exe" 601 | if config.compilers_path and not os.path.exists(mw_path): 602 | sys.exit(f"Linker {mw_path} does not exist") 603 | 604 | ### 605 | # Link 606 | ### 607 | for step in link_steps: 608 | step.write(n) 609 | n.newline() 610 | 611 | ### 612 | # Generate RELs 613 | ### 614 | rel_outputs = list( 615 | map( 616 | lambda step: step.output(), 617 | filter(lambda step: step.module_id != 0, link_steps), 618 | ) 619 | ) 620 | if len(rel_outputs) > 0: 621 | n.comment("Generate RELs") 622 | n.build( 623 | outputs=path(rel_outputs), 624 | rule="makerel", 625 | inputs=path(list(map(lambda step: step.partial_output(), link_steps))), 626 | implicit=path([dtk, config.config_path]), 627 | variables={"config": path(config.config_path)}, 628 | ) 629 | n.newline() 630 | 631 | ### 632 | # Helper rule for building all source files 633 | ### 634 | n.comment("Build all source files") 635 | n.build( 636 | outputs="all_source", 637 | rule="phony", 638 | inputs=path(source_inputs), 639 | ) 640 | n.newline() 641 | 642 | ### 643 | # Helper rule for building all source files, with a host compiler 644 | ### 645 | n.comment("Build all source files with a host compiler") 646 | n.build( 647 | outputs="all_source_host", 648 | rule="phony", 649 | inputs=path(host_source_inputs), 650 | ) 651 | n.newline() 652 | 653 | ### 654 | # Check hash 655 | ### 656 | n.comment("Check hash") 657 | ok_path = build_path / "ok" 658 | quiet = "-q " if len(link_steps) > 3 else "" 659 | n.rule( 660 | name="check", 661 | command=f"{dtk} shasum {quiet} -c $in -o $out", 662 | description="CHECK $in", 663 | ) 664 | n.build( 665 | outputs=path(ok_path), 666 | rule="check", 667 | inputs=path(config.check_sha_path), 668 | implicit=path([dtk, *map(lambda step: step.output(), link_steps)]), 669 | ) 670 | n.newline() 671 | 672 | ### 673 | # Calculate progress 674 | ### 675 | n.comment("Calculate progress") 676 | progress_path = build_path / "progress.json" 677 | n.rule( 678 | name="progress", 679 | command=f"$python {configure_script} $configure_args progress", 680 | description="PROGRESS", 681 | ) 682 | n.build( 683 | outputs=path(progress_path), 684 | rule="progress", 685 | implicit=path([ok_path, configure_script, python_lib, config.config_path]), 686 | ) 687 | 688 | ### 689 | # Helper tools 690 | ### 691 | # TODO: make these rules work for RELs too 692 | dol_link_step = link_steps[0] 693 | dol_elf_path = dol_link_step.partial_output() 694 | n.comment("Check for mismatching symbols") 695 | n.rule( 696 | name="dol_diff", 697 | command=f"{dtk} -L error dol diff $in", 698 | description=f"DIFF {dol_elf_path}", 699 | ) 700 | n.build( 701 | inputs=path([config.config_path, dol_elf_path]), 702 | outputs="dol_diff", 703 | rule="dol_diff", 704 | ) 705 | n.build( 706 | outputs="diff", 707 | rule="phony", 708 | inputs="dol_diff", 709 | ) 710 | n.newline() 711 | 712 | n.comment("Apply symbols from linked ELF") 713 | n.rule( 714 | name="dol_apply", 715 | command=f"{dtk} dol apply $in", 716 | description=f"APPLY {dol_elf_path}", 717 | ) 718 | n.build( 719 | inputs=path([config.config_path, dol_elf_path]), 720 | outputs="dol_apply", 721 | rule="dol_apply", 722 | implicit=path([ok_path]), 723 | ) 724 | n.build( 725 | outputs="apply", 726 | rule="phony", 727 | inputs="dol_apply", 728 | ) 729 | n.newline() 730 | 731 | ### 732 | # Split DOL 733 | ### 734 | n.comment("Split DOL into relocatable objects") 735 | n.rule( 736 | name="split", 737 | command=f"{dtk} dol split $in $out_dir", 738 | description="SPLIT $in", 739 | depfile="$out_dir/dep", 740 | deps="gcc", 741 | ) 742 | n.build( 743 | inputs=path(config.config_path), 744 | outputs=path(build_config_path), 745 | rule="split", 746 | implicit=path(dtk), 747 | variables={"out_dir": path(build_path)}, 748 | ) 749 | n.newline() 750 | 751 | ### 752 | # Regenerate on change 753 | ### 754 | n.comment("Reconfigure on change") 755 | n.rule( 756 | name="configure", 757 | command=f"$python {configure_script} $configure_args", 758 | generator=True, 759 | description=f"RUN {configure_script}", 760 | ) 761 | n.build( 762 | outputs="build.ninja", 763 | rule="configure", 764 | implicit=path( 765 | [ 766 | build_config_path, 767 | configure_script, 768 | python_lib, 769 | Path(python_lib_dir) / "ninja_syntax.py", 770 | ] 771 | ), 772 | ) 773 | n.newline() 774 | 775 | ### 776 | # Default rule 777 | ### 778 | n.comment("Default rule") 779 | if build_config: 780 | n.default(path(progress_path)) 781 | else: 782 | n.default(path(build_config_path)) 783 | 784 | # Write build.ninja 785 | with open("build.ninja", "w", encoding="utf-8") as f: 786 | f.write(out.getvalue()) 787 | out.close() 788 | 789 | 790 | # Generate objdiff.json 791 | def generate_objdiff_config(config, build_config): 792 | if not build_config: 793 | return 794 | 795 | objdiff_config = { 796 | "min_version": "0.4.3", 797 | "custom_make": "ninja", 798 | "build_target": False, 799 | "watch_patterns": [ 800 | "*.c", 801 | "*.cp", 802 | "*.cpp", 803 | "*.h", 804 | "*.hpp", 805 | "*.inc", 806 | "*.py", 807 | "*.yml", 808 | "*.txt", 809 | "*.json", 810 | ], 811 | "units": [], 812 | } 813 | 814 | build_path = config.out_path() 815 | 816 | def add_unit(build_obj, module_name): 817 | if build_obj["autogenerated"]: 818 | # Skip autogenerated objects 819 | return 820 | 821 | obj_path, obj_name = build_obj["object"], build_obj["name"] 822 | base_object = Path(obj_name).with_suffix("") 823 | unit_config = { 824 | "name": unix_str(Path(module_name) / base_object), 825 | "target_path": unix_str(obj_path), 826 | } 827 | 828 | result = config.find_object(obj_name) 829 | if not result: 830 | objdiff_config["units"].append(unit_config) 831 | return 832 | 833 | lib, obj = result 834 | unit_src_path = config.src_dir / obj.options["source"] 835 | if not unit_src_path.exists(): 836 | objdiff_config["units"].append(unit_config) 837 | return 838 | 839 | cflags = obj.options["cflags"] or lib["cflags"] 840 | src_obj_path = build_path / "src" / f"{base_object}.o" 841 | 842 | reverse_fn_order = False 843 | if type(cflags) is list: 844 | for flag in cflags: 845 | if not flag.startswith("-inline "): 846 | continue 847 | for value in flag.split(" ")[1].split(","): 848 | if value == "deferred": 849 | reverse_fn_order = True 850 | elif value == "nodeferred": 851 | reverse_fn_order = False 852 | 853 | unit_config["base_path"] = unix_str(src_obj_path) 854 | unit_config["reverse_fn_order"] = reverse_fn_order 855 | unit_config["complete"] = obj.completed 856 | objdiff_config["units"].append(unit_config) 857 | 858 | # Add DOL units 859 | for unit in build_config["units"]: 860 | add_unit(unit, build_config["name"]) 861 | 862 | # Add REL units 863 | for module in build_config["modules"]: 864 | for unit in module["units"]: 865 | add_unit(unit, module["name"]) 866 | 867 | # Write objdiff.json 868 | with open("objdiff.json", "w", encoding="utf-8") as w: 869 | json.dump(objdiff_config, w, indent=4) 870 | 871 | 872 | # Calculate, print and write progress to progress.json 873 | def calculate_progress(config): 874 | out_path = config.out_path() 875 | build_config = load_build_config(config, out_path / "config.json") 876 | if not build_config: 877 | return 878 | 879 | class ProgressUnit: 880 | def __init__(self, name): 881 | self.name = name 882 | self.code_total = 0 883 | self.code_progress = 0 884 | self.data_total = 0 885 | self.data_progress = 0 886 | self.objects_progress = 0 887 | self.objects_total = 0 888 | self.objects = set() 889 | 890 | def add(self, build_obj): 891 | self.code_total += build_obj["code_size"] 892 | self.data_total += build_obj["data_size"] 893 | 894 | # Avoid counting the same object in different modules twice 895 | include_object = build_obj["name"] not in self.objects 896 | if include_object: 897 | self.objects.add(build_obj["name"]) 898 | self.objects_total += 1 899 | 900 | if build_obj["autogenerated"]: 901 | # Skip autogenerated objects 902 | return 903 | 904 | result = config.find_object(build_obj["name"]) 905 | if not result: 906 | return 907 | 908 | _, obj = result 909 | if not obj.completed: 910 | return 911 | 912 | self.code_progress += build_obj["code_size"] 913 | self.data_progress += build_obj["data_size"] 914 | if include_object: 915 | self.objects_progress += 1 916 | 917 | def code_frac(self): 918 | return self.code_progress / self.code_total 919 | 920 | def data_frac(self): 921 | return self.data_progress / self.data_total 922 | 923 | # Add DOL units 924 | all_progress = ProgressUnit("All") if config.progress_all else None 925 | dol_progress = ProgressUnit("DOL") 926 | for unit in build_config["units"]: 927 | if all_progress: 928 | all_progress.add(unit) 929 | dol_progress.add(unit) 930 | 931 | # Add REL units 932 | rels_progress = ProgressUnit("Modules") if config.progress_modules else None 933 | modules_progress = [] 934 | for module in build_config["modules"]: 935 | progress = ProgressUnit(module["name"]) 936 | modules_progress.append(progress) 937 | for unit in module["units"]: 938 | if all_progress: 939 | all_progress.add(unit) 940 | if rels_progress: 941 | rels_progress.add(unit) 942 | progress.add(unit) 943 | 944 | # Print human-readable progress 945 | print("Progress:") 946 | 947 | def print_category(unit): 948 | code_frac = unit.code_frac() 949 | data_frac = unit.data_frac() 950 | print( 951 | f" {unit.name}: {code_frac:.2%} code, {data_frac:.2%} data ({unit.objects_progress} / {unit.objects_total} files)" 952 | ) 953 | print(f" Code: {unit.code_progress} / {unit.code_total} bytes") 954 | print(f" Data: {unit.data_progress} / {unit.data_total} bytes") 955 | 956 | if all_progress: 957 | print_category(all_progress) 958 | print_category(dol_progress) 959 | module_count = len(build_config["modules"]) 960 | if module_count > 0: 961 | print_category(rels_progress) 962 | if config.progress_each_module: 963 | for progress in modules_progress: 964 | print_category(progress) 965 | 966 | # Generate and write progress.json 967 | progress_json = {} 968 | 969 | def add_category(category, unit): 970 | progress_json[category] = { 971 | "code": unit.code_progress, 972 | "code/total": unit.code_total, 973 | "data": unit.data_progress, 974 | "data/total": unit.data_total, 975 | } 976 | 977 | if all_progress: 978 | add_category("all", all_progress) 979 | add_category("dol", dol_progress) 980 | if len(build_config["modules"]) > 0: 981 | if rels_progress: 982 | add_category("modules", rels_progress) 983 | if config.progress_each_module: 984 | for progress in modules_progress: 985 | add_category(progress.name, progress) 986 | with open(out_path / "progress.json", "w", encoding="utf-8") as w: 987 | json.dump(progress_json, w, indent=4) 988 | -------------------------------------------------------------------------------- /tools/transform_dep.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ### 4 | # Transforms .d files, converting Windows paths to Unix paths. 5 | # Allows usage of the mwcc -MMD flag on platforms other than Windows. 6 | # 7 | # Usage: 8 | # python3 tools/transform_dep.py build/src/file.d build/src/file.d 9 | # 10 | # If changes are made, please submit a PR to 11 | # https://github.com/encounter/dtk-template 12 | ### 13 | 14 | import argparse 15 | import os 16 | from platform import uname 17 | 18 | wineprefix = os.path.join(os.environ["HOME"], ".wine") 19 | if "WINEPREFIX" in os.environ: 20 | wineprefix = os.environ["WINEPREFIX"] 21 | winedevices = os.path.join(wineprefix, "dosdevices") 22 | 23 | 24 | def in_wsl() -> bool: 25 | return "microsoft-standard" in uname().release 26 | 27 | 28 | def import_d_file(in_file) -> str: 29 | out_text = "" 30 | 31 | with open(in_file) as file: 32 | for idx, line in enumerate(file): 33 | if idx == 0: 34 | if line.endswith(" \\\n"): 35 | out_text += line[:-3].replace("\\", "/") + " \\\n" 36 | else: 37 | out_text += line.replace("\\", "/") 38 | else: 39 | suffix = "" 40 | if line.endswith(" \\\n"): 41 | suffix = " \\" 42 | path = line.lstrip()[:-3] 43 | else: 44 | path = line.strip() 45 | # lowercase drive letter 46 | path = path[0].lower() + path[1:] 47 | if path[0] == "z": 48 | # shortcut for z: 49 | path = path[2:].replace("\\", "/") 50 | elif in_wsl(): 51 | path = path[0:1] + path[2:] 52 | path = os.path.join("/mnt", path.replace("\\", "/")) 53 | else: 54 | # use $WINEPREFIX/dosdevices to resolve path 55 | path = os.path.realpath( 56 | os.path.join(winedevices, path.replace("\\", "/")) 57 | ) 58 | out_text += "\t" + path + suffix + "\n" 59 | 60 | return out_text 61 | 62 | 63 | def main(): 64 | parser = argparse.ArgumentParser( 65 | description="""Transform a .d file from Wine paths to normal paths""" 66 | ) 67 | parser.add_argument( 68 | "d_file", 69 | help="""Dependency file in""", 70 | ) 71 | parser.add_argument( 72 | "d_file_out", 73 | help="""Dependency file out""", 74 | ) 75 | args = parser.parse_args() 76 | 77 | output = import_d_file(args.d_file) 78 | 79 | with open(args.d_file_out, "w", encoding="UTF-8") as f: 80 | f.write(output) 81 | 82 | 83 | if __name__ == "__main__": 84 | main() 85 | -------------------------------------------------------------------------------- /tools/upload_progress.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ### 4 | # Uploads progress information to https://github.com/decompals/frogress. 5 | # 6 | # Usage: 7 | # python3 tools/upload_progress.py -b https://progress.decomp.club/ -p [project] -v [version] build/[version]/progress.json 8 | # 9 | # If changes are made, please submit a PR to 10 | # https://github.com/encounter/dtk-template 11 | ### 12 | 13 | import argparse 14 | import json 15 | import os 16 | import requests 17 | import subprocess 18 | import sys 19 | 20 | 21 | def get_git_commit_timestamp() -> int: 22 | return int( 23 | subprocess.check_output(["git", "show", "-s", "--format=%ct"]) 24 | .decode("ascii") 25 | .rstrip() 26 | ) 27 | 28 | 29 | def get_git_commit_sha() -> str: 30 | return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip() 31 | 32 | 33 | def generate_url(args: argparse.Namespace) -> str: 34 | url_components = [args.base_url.rstrip("/"), "data"] 35 | 36 | for arg in [args.project, args.version]: 37 | if arg != "": 38 | url_components.append(arg) 39 | 40 | return str.join("/", url_components) + "/" 41 | 42 | 43 | if __name__ == "__main__": 44 | parser = argparse.ArgumentParser(description="Upload progress information.") 45 | parser.add_argument("-b", "--base_url", help="API base URL", required=True) 46 | parser.add_argument("-a", "--api_key", help="API key (env var PROGRESS_API_KEY)") 47 | parser.add_argument("-p", "--project", help="Project slug", required=True) 48 | parser.add_argument("-v", "--version", help="Version slug", required=True) 49 | parser.add_argument("input", help="Progress JSON input") 50 | 51 | args = parser.parse_args() 52 | api_key = args.api_key or os.environ.get("PROGRESS_API_KEY") 53 | if not api_key: 54 | raise "API key required" 55 | url = generate_url(args) 56 | 57 | entries = [] 58 | with open(args.input, "r") as f: 59 | data = json.load(f) 60 | entries.append( 61 | { 62 | "timestamp": get_git_commit_timestamp(), 63 | "git_hash": get_git_commit_sha(), 64 | "categories": data, 65 | } 66 | ) 67 | 68 | print("Publishing entry to", url) 69 | json.dump(entries[0], sys.stdout, indent=4) 70 | print() 71 | r = requests.post(url, json={ 72 | "api_key": api_key, 73 | "entries": entries, 74 | }) 75 | r.raise_for_status() 76 | print("Done!") 77 | --------------------------------------------------------------------------------