├── .gitignore ├── menu_entries ├── de.bin ├── es.bin ├── fr.bin ├── it.bin ├── jp.bin ├── en-uk.bin ├── en-us.bin └── misc.bin ├── assets ├── title_item │ ├── tex_1.png │ ├── tex_2.png │ ├── tex_3.png │ ├── tex_4.png │ ├── tex_5.png │ ├── tex_6.png │ ├── tex_7.png │ ├── tex_8.png │ ├── tex_9.png │ ├── tex_10.png │ ├── tex_11.png │ ├── tex_12.png │ ├── tex_13.png │ ├── tex_14.png │ ├── tex_15.png │ ├── tex_16.png │ ├── tex_17.png │ ├── tex_18.png │ ├── tex_19.png │ ├── tex_20.png │ ├── tex_21.png │ ├── tex_22.png │ ├── tex_23.png │ ├── tex_24.png │ ├── tex_25.png │ ├── tex_26.png │ ├── tex_27.png │ ├── tex_28.png │ ├── tex_29.png │ ├── tex_30.png │ ├── tex_31.png │ ├── tex_32.png │ ├── tex_33.png │ ├── tex_34.png │ ├── tex_35.png │ ├── tex_36.png │ ├── tex_37.png │ ├── tex_38.png │ ├── tex_39.png │ ├── tex_40.png │ ├── tex_41.png │ ├── tex_42.png │ ├── tex_43.png │ ├── arcade_mode.png │ ├── arcade_modus.png │ ├── mode_arcade.png │ ├── modo_arcade.png │ ├── modalita_arcade.png │ ├── simulation_mode.png │ ├── gran_turismo_mode.png │ ├── mode_gran_turismo.png │ ├── modo_gran_turismo.png │ ├── gran_turismo_modus.png │ ├── modalita_gran_turismo.png │ └── definitions.json └── title_gtmode │ ├── title_gtmode_new.png │ └── title_gtmode_us_new.png ├── tools ├── mkpsxiso │ ├── mkpsxiso.exe │ ├── dumpsxiso.exe │ └── LICENSE.md └── GTVolTool │ ├── GTVolTool.exe │ ├── ICSharpCode.SharpZipLib.dll │ └── GTVolTool.exe.config ├── .gitmodules ├── vol_replacements ├── arcade │ ├── title_item.tim.gz │ ├── title_gtmode.tim.gz │ ├── title_gtmode_jp.tim.gz │ └── title_gtmode_us.tim.gz └── file.hashes ├── LICENSE ├── README.md └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.vscode/ 2 | -------------------------------------------------------------------------------- /menu_entries/de.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/de.bin -------------------------------------------------------------------------------- /menu_entries/es.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/es.bin -------------------------------------------------------------------------------- /menu_entries/fr.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/fr.bin -------------------------------------------------------------------------------- /menu_entries/it.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/it.bin -------------------------------------------------------------------------------- /menu_entries/jp.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/jp.bin -------------------------------------------------------------------------------- /menu_entries/en-uk.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/en-uk.bin -------------------------------------------------------------------------------- /menu_entries/en-us.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/en-us.bin -------------------------------------------------------------------------------- /menu_entries/misc.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/menu_entries/misc.bin -------------------------------------------------------------------------------- /assets/title_item/tex_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_1.png -------------------------------------------------------------------------------- /assets/title_item/tex_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_2.png -------------------------------------------------------------------------------- /assets/title_item/tex_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_3.png -------------------------------------------------------------------------------- /assets/title_item/tex_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_4.png -------------------------------------------------------------------------------- /assets/title_item/tex_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_5.png -------------------------------------------------------------------------------- /assets/title_item/tex_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_6.png -------------------------------------------------------------------------------- /assets/title_item/tex_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_7.png -------------------------------------------------------------------------------- /assets/title_item/tex_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_8.png -------------------------------------------------------------------------------- /assets/title_item/tex_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_9.png -------------------------------------------------------------------------------- /tools/mkpsxiso/mkpsxiso.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/tools/mkpsxiso/mkpsxiso.exe -------------------------------------------------------------------------------- /assets/title_item/tex_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_10.png -------------------------------------------------------------------------------- /assets/title_item/tex_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_11.png -------------------------------------------------------------------------------- /assets/title_item/tex_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_12.png -------------------------------------------------------------------------------- /assets/title_item/tex_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_13.png -------------------------------------------------------------------------------- /assets/title_item/tex_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_14.png -------------------------------------------------------------------------------- /assets/title_item/tex_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_15.png -------------------------------------------------------------------------------- /assets/title_item/tex_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_16.png -------------------------------------------------------------------------------- /assets/title_item/tex_17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_17.png -------------------------------------------------------------------------------- /assets/title_item/tex_18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_18.png -------------------------------------------------------------------------------- /assets/title_item/tex_19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_19.png -------------------------------------------------------------------------------- /assets/title_item/tex_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_20.png -------------------------------------------------------------------------------- /assets/title_item/tex_21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_21.png -------------------------------------------------------------------------------- /assets/title_item/tex_22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_22.png -------------------------------------------------------------------------------- /assets/title_item/tex_23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_23.png -------------------------------------------------------------------------------- /assets/title_item/tex_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_24.png -------------------------------------------------------------------------------- /assets/title_item/tex_25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_25.png -------------------------------------------------------------------------------- /assets/title_item/tex_26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_26.png -------------------------------------------------------------------------------- /assets/title_item/tex_27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_27.png -------------------------------------------------------------------------------- /assets/title_item/tex_28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_28.png -------------------------------------------------------------------------------- /assets/title_item/tex_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_29.png -------------------------------------------------------------------------------- /assets/title_item/tex_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_30.png -------------------------------------------------------------------------------- /assets/title_item/tex_31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_31.png -------------------------------------------------------------------------------- /assets/title_item/tex_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_32.png -------------------------------------------------------------------------------- /assets/title_item/tex_33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_33.png -------------------------------------------------------------------------------- /assets/title_item/tex_34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_34.png -------------------------------------------------------------------------------- /assets/title_item/tex_35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_35.png -------------------------------------------------------------------------------- /assets/title_item/tex_36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_36.png -------------------------------------------------------------------------------- /assets/title_item/tex_37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_37.png -------------------------------------------------------------------------------- /assets/title_item/tex_38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_38.png -------------------------------------------------------------------------------- /assets/title_item/tex_39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_39.png -------------------------------------------------------------------------------- /assets/title_item/tex_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_40.png -------------------------------------------------------------------------------- /assets/title_item/tex_41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_41.png -------------------------------------------------------------------------------- /assets/title_item/tex_42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_42.png -------------------------------------------------------------------------------- /assets/title_item/tex_43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/tex_43.png -------------------------------------------------------------------------------- /tools/GTVolTool/GTVolTool.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/tools/GTVolTool/GTVolTool.exe -------------------------------------------------------------------------------- /tools/mkpsxiso/dumpsxiso.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/tools/mkpsxiso/dumpsxiso.exe -------------------------------------------------------------------------------- /assets/title_item/arcade_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/arcade_mode.png -------------------------------------------------------------------------------- /assets/title_item/arcade_modus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/arcade_modus.png -------------------------------------------------------------------------------- /assets/title_item/mode_arcade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/mode_arcade.png -------------------------------------------------------------------------------- /assets/title_item/modo_arcade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/modo_arcade.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "gttools"] 2 | path = gttools 3 | url = https://github.com/CookiePLMonster/GTModTools.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /assets/title_item/modalita_arcade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/modalita_arcade.png -------------------------------------------------------------------------------- /assets/title_item/simulation_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/simulation_mode.png -------------------------------------------------------------------------------- /assets/title_item/gran_turismo_mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/gran_turismo_mode.png -------------------------------------------------------------------------------- /assets/title_item/mode_gran_turismo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/mode_gran_turismo.png -------------------------------------------------------------------------------- /assets/title_item/modo_gran_turismo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/modo_gran_turismo.png -------------------------------------------------------------------------------- /assets/title_gtmode/title_gtmode_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_gtmode/title_gtmode_new.png -------------------------------------------------------------------------------- /assets/title_item/gran_turismo_modus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/gran_turismo_modus.png -------------------------------------------------------------------------------- /vol_replacements/arcade/title_item.tim.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/vol_replacements/arcade/title_item.tim.gz -------------------------------------------------------------------------------- /assets/title_gtmode/title_gtmode_us_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_gtmode/title_gtmode_us_new.png -------------------------------------------------------------------------------- /assets/title_item/modalita_gran_turismo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/assets/title_item/modalita_gran_turismo.png -------------------------------------------------------------------------------- /tools/GTVolTool/ICSharpCode.SharpZipLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/tools/GTVolTool/ICSharpCode.SharpZipLib.dll -------------------------------------------------------------------------------- /vol_replacements/arcade/title_gtmode.tim.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/vol_replacements/arcade/title_gtmode.tim.gz -------------------------------------------------------------------------------- /vol_replacements/arcade/title_gtmode_jp.tim.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/vol_replacements/arcade/title_gtmode_jp.tim.gz -------------------------------------------------------------------------------- /vol_replacements/arcade/title_gtmode_us.tim.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CookiePLMonster/GT2-Combined-Disc/HEAD/vol_replacements/arcade/title_gtmode_us.tim.gz -------------------------------------------------------------------------------- /vol_replacements/file.hashes: -------------------------------------------------------------------------------- 1 | 5DB15FAC = arcade/title_gtmode.tim.gz 2 | 5DB15FAC = arcade/title_gtmode_jp.tim.gz 3 | 40CEEBFC = arcade/title_gtmode_us.tim.gz 4 | -------------------------------------------------------------------------------- /tools/GTVolTool/GTVolTool.exe.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Adrian Zdanowicz (Silent) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gran Turismo 2 Combined Disc 2 | 3 | Gran Turismo 2, other than being one of the more fondly remembered installments of the franchise, has one unique aspect 4 | not seen in any other Gran Turismo to date -- it's split between two discs. 5 | This modification combines both discs for an ultimate and complete version of Gran Turismo 2. 6 | 7 | Due to the nature of this mod, the setup process is slightly more involved than the usual: 8 | 1. Download the setup script. **Do note that GTVolTool used by this script is Windows only.** 9 | 2. Install **Python 3.8.0** or newer. If you don't have it installed yet, Python can be downloaded from here: 10 | * Standalone: 11 | * Microsoft Store: 12 | 3. Run `setup.py` by double-clicking it like any other executable file. If due to your local setup the script does not run, 13 | launch it with `python setup.py` or `python3 setup.py` in the Command Prompt. 14 | 4. Follow the on-screen instructions. The script will bring up a system file picker to select files by default, but this may be changed by starting the script with a `-t` parameter. 15 | Remember that you may easily "type" the full path to the file by dragging it to the command line window - it's useful for easily putting full paths to the Arcade and Simulation discs. 16 | 5. Wait for the setup to complete. Please be patient - it takes a while, as it needs to repack discs and the game assets. 17 | 18 | ## Version compatibility 19 | The modification is compatible with all game versions, **except for NTSC-J v1.0**. 20 | 21 | ## Hardware compatibility 22 | * PSP/PS Vita can use the full version of the mod in PBP format. 23 | * On PS1, the full version is compatible with [XStation](https://castlemaniagames.com/products/xstation) and [PSIO](https://ps-io.com/). 24 | You should opt for the lightweight version (without FMVs) **only** if burning the image on a physical CD. 25 | 26 | [![Preview](http://img.youtube.com/vi/jByvSCDQLdY/0.jpg)](http://www.youtube.com/watch?v=jByvSCDQLdY "Preview") 27 | -------------------------------------------------------------------------------- /assets/title_item/definitions.json: -------------------------------------------------------------------------------- 1 | { 2 | "entries": { 3 | "de": [ 4 | "arcade_modus.png", 5 | "gran_turismo_modus.png", 6 | "tex_27.png", 7 | "tex_28.png", 8 | "tex_29.png", 9 | "tex_30.png", 10 | "tex_31.png" 11 | ], 12 | "en-uk": [ 13 | "arcade_mode.png", 14 | "gran_turismo_mode.png", 15 | "tex_15.png", 16 | "tex_16.png", 17 | "tex_17.png", 18 | "tex_18.png", 19 | "tex_19.png" 20 | ], 21 | "en-us": [ 22 | "arcade_mode.png", 23 | "simulation_mode.png", 24 | "tex_9.png", 25 | "tex_10.png", 26 | "tex_11.png", 27 | "tex_12.png", 28 | "tex_13.png" 29 | ], 30 | "es": [ 31 | "modo_arcade.png", 32 | "modo_gran_turismo.png", 33 | "tex_39.png", 34 | "tex_40.png", 35 | "tex_41.png", 36 | "tex_42.png", 37 | "tex_43.png" 38 | ], 39 | "fr": [ 40 | "mode_arcade.png", 41 | "mode_gran_turismo.png", 42 | "tex_21.png", 43 | "tex_22.png", 44 | "tex_23.png", 45 | "tex_24.png", 46 | "tex_25.png" 47 | ], 48 | "it": [ 49 | "modalita_arcade.png", 50 | "modalita_gran_turismo.png", 51 | "tex_33.png", 52 | "tex_34.png", 53 | "tex_35.png", 54 | "tex_36.png", 55 | "tex_37.png" 56 | ], 57 | "jp": [ 58 | "arcade_mode.png", 59 | "gran_turismo_mode.png", 60 | "tex_3.png", 61 | "tex_4.png", 62 | "tex_5.png", 63 | "tex_6.png", 64 | "tex_7.png" 65 | ], 66 | "misc": [ 67 | "tex_1.png" 68 | ] 69 | }, 70 | "textures": { 71 | "arcade_mode.png": { 72 | "height": 21, 73 | "palette": 15730, 74 | "texture_page": 13, 75 | "width": 90, 76 | "x": 0, 77 | "y": 67 78 | }, 79 | "arcade_modus.png": { 80 | "height": 21, 81 | "palette": 15728, 82 | "texture_page": 13, 83 | "width": 96, 84 | "x": 88, 85 | "y": 23 86 | }, 87 | "gran_turismo_mode.png": { 88 | "height": 22, 89 | "palette": 15602, 90 | "texture_page": 12, 91 | "width": 119, 92 | "x": 120, 93 | "y": 123 94 | }, 95 | "gran_turismo_modus.png": { 96 | "height": 22, 97 | "palette": 15543, 98 | "texture_page": 12, 99 | "width": 126, 100 | "x": 0, 101 | "y": 101 102 | }, 103 | "modalita_arcade.png": { 104 | "height": 21, 105 | "palette": 15606, 106 | "texture_page": 12, 107 | "width": 107, 108 | "x": 0, 109 | "y": 168 110 | }, 111 | "modalita_gran_turismo.png": { 112 | "height": 22, 113 | "palette": 15537, 114 | "texture_page": 12, 115 | "width": 137, 116 | "x": 0, 117 | "y": 24 118 | }, 119 | "mode_arcade.png": { 120 | "height": 21, 121 | "palette": 15731, 122 | "texture_page": 13, 123 | "width": 90, 124 | "x": 90, 125 | "y": 67 126 | }, 127 | "mode_gran_turismo.png": { 128 | "height": 22, 129 | "palette": 15600, 130 | "texture_page": 12, 131 | "width": 120, 132 | "x": 126, 133 | "y": 101 134 | }, 135 | "modo_arcade.png": { 136 | "height": 21, 137 | "palette": 15732, 138 | "texture_page": 13, 139 | "width": 90, 140 | "x": 0, 141 | "y": 88 142 | }, 143 | "modo_gran_turismo.png": { 144 | "height": 22, 145 | "palette": 15601, 146 | "texture_page": 12, 147 | "width": 120, 148 | "x": 0, 149 | "y": 123 150 | }, 151 | "simulation_mode.png": { 152 | "height": 22, 153 | "palette": 15605, 154 | "texture_page": 12, 155 | "width": 104, 156 | "x": 108, 157 | "y": 166 158 | }, 159 | "tex_1.png": { 160 | "height": 24, 161 | "palette": 15536, 162 | "texture_page": 12, 163 | "width": 256, 164 | "x": 0, 165 | "y": 0 166 | }, 167 | "tex_10.png": { 168 | "height": 23, 169 | "palette": 15858, 170 | "texture_page": 13, 171 | "width": 52, 172 | "x": 0, 173 | "y": 150 174 | }, 175 | "tex_11.png": { 176 | "height": 21, 177 | "palette": 15796, 178 | "texture_page": 13, 179 | "width": 72, 180 | "x": 184, 181 | "y": 23 182 | }, 183 | "tex_12.png": { 184 | "height": 20, 185 | "palette": 15798, 186 | "texture_page": 13, 187 | "width": 72, 188 | "x": 0, 189 | "y": 130 190 | }, 191 | "tex_13.png": { 192 | "height": 21, 193 | "palette": 15793, 194 | "texture_page": 13, 195 | "width": 84, 196 | "x": 0, 197 | "y": 109 198 | }, 199 | "tex_15.png": { 200 | "height": 23, 201 | "palette": 15670, 202 | "texture_page": 13, 203 | "width": 88, 204 | "x": 92, 205 | "y": 0 206 | }, 207 | "tex_16.png": { 208 | "height": 23, 209 | "palette": 15859, 210 | "texture_page": 13, 211 | "width": 52, 212 | "x": 0, 213 | "y": 173 214 | }, 215 | "tex_17.png": { 216 | "height": 21, 217 | "palette": 15797, 218 | "texture_page": 13, 219 | "width": 72, 220 | "x": 180, 221 | "y": 67 222 | }, 223 | "tex_18.png": { 224 | "height": 20, 225 | "palette": 15799, 226 | "texture_page": 13, 227 | "width": 72, 228 | "x": 168, 229 | "y": 111 230 | }, 231 | "tex_19.png": { 232 | "height": 21, 233 | "palette": 15794, 234 | "texture_page": 13, 235 | "width": 84, 236 | "x": 84, 237 | "y": 111 238 | }, 239 | "tex_21.png": { 240 | "height": 24, 241 | "palette": 15607, 242 | "texture_page": 12, 243 | "width": 92, 244 | "x": 0, 245 | "y": 189 246 | }, 247 | "tex_22.png": { 248 | "height": 23, 249 | "palette": 15860, 250 | "texture_page": 13, 251 | "width": 52, 252 | "x": 0, 253 | "y": 196 254 | }, 255 | "tex_23.png": { 256 | "height": 23, 257 | "palette": 15541, 258 | "texture_page": 12, 259 | "width": 124, 260 | "x": 0, 261 | "y": 69 262 | }, 263 | "tex_24.png": { 264 | "height": 27, 265 | "palette": 15539, 266 | "texture_page": 12, 267 | "width": 108, 268 | "x": 137, 269 | "y": 24 270 | }, 271 | "tex_25.png": { 272 | "height": 24, 273 | "palette": 15540, 274 | "texture_page": 12, 275 | "width": 120, 276 | "x": 128, 277 | "y": 51 278 | }, 279 | "tex_27.png": { 280 | "height": 23, 281 | "palette": 15538, 282 | "texture_page": 12, 283 | "width": 128, 284 | "x": 0, 285 | "y": 46 286 | }, 287 | "tex_28.png": { 288 | "height": 23, 289 | "palette": 15856, 290 | "texture_page": 13, 291 | "width": 60, 292 | "x": 168, 293 | "y": 131 294 | }, 295 | "tex_29.png": { 296 | "height": 23, 297 | "palette": 15665, 298 | "texture_page": 12, 299 | "width": 92, 300 | "x": 92, 301 | "y": 189 302 | }, 303 | "tex_3.png": { 304 | "height": 24, 305 | "palette": 15666, 306 | "texture_page": 12, 307 | "width": 88, 308 | "x": 92, 309 | "y": 212 310 | }, 311 | "tex_30.png": { 312 | "height": 23, 313 | "palette": 15795, 314 | "texture_page": 13, 315 | "width": 72, 316 | "x": 184, 317 | "y": 0 318 | }, 319 | "tex_31.png": { 320 | "height": 23, 321 | "palette": 15603, 322 | "texture_page": 12, 323 | "width": 108, 324 | "x": 0, 325 | "y": 145 326 | }, 327 | "tex_33.png": { 328 | "height": 23, 329 | "palette": 15734, 330 | "texture_page": 13, 331 | "width": 80, 332 | "x": 172, 333 | "y": 44 334 | }, 335 | "tex_34.png": { 336 | "height": 23, 337 | "palette": 15861, 338 | "texture_page": 13, 339 | "width": 52, 340 | "x": 0, 341 | "y": 219 342 | }, 343 | "tex_35.png": { 344 | "height": 23, 345 | "palette": 15735, 346 | "texture_page": 13, 347 | "width": 80, 348 | "x": 90, 349 | "y": 88 350 | }, 351 | "tex_36.png": { 352 | "height": 23, 353 | "palette": 15729, 354 | "texture_page": 13, 355 | "width": 84, 356 | "x": 88, 357 | "y": 44 358 | }, 359 | "tex_37.png": { 360 | "height": 21, 361 | "palette": 15604, 362 | "texture_page": 12, 363 | "width": 112, 364 | "x": 108, 365 | "y": 145 366 | }, 367 | "tex_39.png": { 368 | "height": 26, 369 | "palette": 15542, 370 | "texture_page": 12, 371 | "width": 108, 372 | "x": 124, 373 | "y": 75 374 | }, 375 | "tex_4.png": { 376 | "height": 24, 377 | "palette": 15862, 378 | "texture_page": 13, 379 | "width": 44, 380 | "x": 52, 381 | "y": 155 382 | }, 383 | "tex_40.png": { 384 | "height": 23, 385 | "palette": 15857, 386 | "texture_page": 13, 387 | "width": 60, 388 | "x": 72, 389 | "y": 132 390 | }, 391 | "tex_41.png": { 392 | "height": 23, 393 | "palette": 15671, 394 | "texture_page": 13, 395 | "width": 88, 396 | "x": 0, 397 | "y": 22 398 | }, 399 | "tex_42.png": { 400 | "height": 23, 401 | "palette": 15792, 402 | "texture_page": 13, 403 | "width": 80, 404 | "x": 170, 405 | "y": 88 406 | }, 407 | "tex_43.png": { 408 | "height": 21, 409 | "palette": 15733, 410 | "texture_page": 13, 411 | "width": 88, 412 | "x": 0, 413 | "y": 45 414 | }, 415 | "tex_5.png": { 416 | "height": 24, 417 | "palette": 15667, 418 | "texture_page": 12, 419 | "width": 72, 420 | "x": 184, 421 | "y": 188 422 | }, 423 | "tex_6.png": { 424 | "height": 22, 425 | "palette": 15668, 426 | "texture_page": 12, 427 | "width": 68, 428 | "x": 180, 429 | "y": 212 430 | }, 431 | "tex_7.png": { 432 | "height": 22, 433 | "palette": 15669, 434 | "texture_page": 13, 435 | "width": 92, 436 | "x": 0, 437 | "y": 0 438 | }, 439 | "tex_9.png": { 440 | "height": 23, 441 | "palette": 15664, 442 | "texture_page": 12, 443 | "width": 92, 444 | "x": 0, 445 | "y": 213 446 | } 447 | } 448 | } -------------------------------------------------------------------------------- /tools/mkpsxiso/LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | from gttools import ovl, PSEXE 3 | from array import array 4 | import argparse 5 | import binascii 6 | import gzip 7 | import io 8 | import os 9 | import re 10 | import shutil 11 | import struct 12 | import subprocess 13 | import sys 14 | import tempfile 15 | import xml.etree.ElementTree as ET 16 | 17 | DEFAULT_OUTPUT_NAME = 'GT2Combined.bin' 18 | 19 | parser = argparse.ArgumentParser(description='Gran Turismo 2 Combined Disc install script. Running the script without any arguments will start Interactive Mode.') 20 | parser.add_argument('-a', '--arcade-disc', type=str, dest='arcade_path', help='path to the Arcade Mode disc') 21 | parser.add_argument('-s', '--simulation-disc', type=str, dest='sim_path', help='path to the Simulation Mode disc') 22 | parser.add_argument('-o', '--output', type=str, dest='output_file', default=DEFAULT_OUTPUT_NAME, help='name of the output file (default: %(default)s)') 23 | parser.add_argument('-f', '--no-fmvs', dest='no_fmvs', action='store_true', help='Do not include movies in the combined disc. This leaves out the intro movie, credits and track previews in Arcade Mode, but allows the disc to be burned on a CD.') 24 | parser.add_argument('-e', '--ignore-errors', dest='ignore_errors', action='store_true', help='ignore non-critical errors encountered during setup. Critical errors are never ignored') 25 | parser.add_argument('-t', '--text-only', dest='text_only', action='store_true', help='Do not use native filepicker windows.') 26 | 27 | cur_python_version, required_python_version = sys.version_info[:3], (3, 8, 0) 28 | if not cur_python_version >= required_python_version: 29 | sys.exit(f"Your Python version {'.'.join(str(i) for i in cur_python_version)} is too old. Please update to Python {'.'.join(str(i) for i in required_python_version)} or newer.") 30 | 31 | def eprint(*args, **kwargs): 32 | print(*args, file=sys.stderr, **kwargs) 33 | 34 | args = parser.parse_args() 35 | interactive_mode = len(tuple(a for a in sys.argv if a not in ("-t", "--text-only"))) == 1 36 | gui_mode = interactive_mode and not args.text_only 37 | if gui_mode: 38 | try: 39 | import tkinter as tk 40 | from tkinter import filedialog 41 | except ImportError: 42 | gui_mode = False 43 | 44 | if interactive_mode: 45 | print( 46 | """ 47 | Gran Turismo 2 Combined Disc install script. 48 | Running the script in Interactive Mode. 49 | 50 | After paths to Arcade and Simulation discs are given, this script will unpack both discs and the VOL file from the Simulation Disc, then patch code and asset. 51 | The setup process may take some time, so please be patient and don't close this window even if the process seems stuck. 52 | """) 53 | if gui_mode: 54 | print("About to open dialogs file paths (re-run the script with -t to run without dialogs).") 55 | input("Press Enter to continue ...") 56 | try: 57 | root = tk.Tk() # init Tk to make filedialog work 58 | root.withdraw() # withdraw because root window not needed 59 | except Exception as e: 60 | gui_mode = False 61 | eprint(f"Forcing text-only mode because of problem initializing Tkinter GUI: {e!r}") 62 | 63 | def getResourcePath(path): 64 | return os.path.join(os.path.dirname(os.path.realpath(__file__)), path) 65 | 66 | def unescapePath(path): 67 | import shlex 68 | return shlex.split(path)[0] 69 | 70 | def main(): 71 | # Utils 72 | class SetupStepFailedError(ValueError): 73 | pass 74 | 75 | def getOutputPath(prompt, default): 76 | prompt_cli = prompt + f' ({default=}): ' 77 | while True: 78 | if gui_mode: 79 | filename = filedialog.asksaveasfilename(initialfile=default, title=prompt, defaultextension=".bin", filetypes=(("BIN file", ".bin"), )) 80 | else: 81 | filename = getResourcePath(unescapePath(input(prompt_cli)) or default) 82 | if not filename: 83 | sys.exit('Setup aborted by user.') 84 | else: 85 | try: 86 | open(filename, 'w+').close() 87 | os.unlink(filename) 88 | return filename 89 | except OSError: 90 | print(f'{filename!r} is not writable!') 91 | 92 | def getInputPath(prompt): 93 | if gui_mode: 94 | while True: 95 | filename = filedialog.askopenfilename(title=prompt, defaultextension=".bin", filetypes=(("BIN file", ".bin .iso"), )) 96 | if not filename: 97 | sys.exit('Setup aborted by user.') 98 | if os.path.isfile(filename): 99 | return filename 100 | print(f'{filename!r} is not a valid file!') 101 | else: 102 | while True: 103 | path = '' 104 | while len(path) == 0: 105 | path = input(prompt + ' ') 106 | path = unescapePath(path) 107 | result = getResourcePath(path) 108 | if os.path.isfile(result): 109 | return result 110 | print(f'{path!r} is not a valid file!') 111 | 112 | def getYesNoAnswer(prompt, default=None): 113 | # Copied from distutils.util since it's deprecated in 3.10 and will be removed in 3.12 114 | def strtobool(val): 115 | """Convert a string representation of truth to True or False. 116 | True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values 117 | are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if 118 | 'val' is anything else. 119 | """ 120 | val = val.lower() 121 | if val in ('y', 'yes', 't', 'true', 'on', '1'): 122 | return True 123 | elif val in ('n', 'no', 'f', 'false', 'off', '0'): 124 | return False 125 | else: 126 | raise ValueError(f"invalid truth value {val!r}") 127 | 128 | try: 129 | default_return = strtobool(default) 130 | default_str = ' [Y/n]: ' if default_return else ' [y/N]: ' 131 | except ValueError: 132 | default_return = None 133 | default_str = ' [y/n]: ' 134 | 135 | while True: 136 | user_input = input(prompt + default_str) 137 | try: 138 | return strtobool(user_input) 139 | except ValueError: 140 | if default_return is None: 141 | print('Please use y/n or yes/no') 142 | else: 143 | return default_return 144 | 145 | def optionalStepFailed(text): 146 | eprint(text) 147 | if interactive_mode: 148 | if not getYesNoAnswer('Continue anyway?'): 149 | sys.exit('Setup aborted by user.') 150 | else: 151 | if not args.ignore_errors: 152 | sys.exit('Setup aborted due to an error.') 153 | 154 | # GZIP stuff 155 | 156 | # This is very nasty, but there seems to be no other clean way to get the size 157 | # of an embedded gzip file, short of reimplementing the entire gzip module 158 | # So let's bruteforce its unpack by increasing size... 159 | def gzipDecompressBruteforce(data): 160 | size = 10 161 | while True: 162 | try: 163 | data_slice = data[:size] 164 | try: 165 | d = gzip.decompress(data_slice) 166 | except EOFError: 167 | # Grow the slice and retry 168 | size += 1 169 | continue 170 | except (LookupError, gzip.BadGzipFile): 171 | # No valid gzip? 172 | return None 173 | 174 | # data_slice is a valid gzip file, get the size and try to extract the filename if it exists! 175 | filename = None 176 | flags, = struct.unpack_from('= (3, 10, 0): 226 | kwargs['ignore_cleanup_errors'] = True 227 | with tempfile.TemporaryDirectory(prefix='gt2combined-', **kwargs) as temp_dir: 228 | 229 | # Installation steps 230 | def stepUnpackDiscs(): 231 | dumpsxiso_exe_path = os.path.join(MKPSXISO_PATH, 'dumpsxiso') 232 | try: 233 | print('Unpacking the Arcade Mode disc...') 234 | arcade_dest = os.path.join(temp_dir, 'disc1') 235 | subprocess.run([dumpsxiso_exe_path, arcade_path, '-x', arcade_dest, '-s', os.path.join(arcade_dest, XML_NAME)], check=True) 236 | 237 | print('Unpacking the Simulation Mode disc...') 238 | sim_dest = os.path.join(temp_dir, 'disc2') 239 | subprocess.run([dumpsxiso_exe_path, sim_path, '-x', sim_dest, '-s', os.path.join(sim_dest, XML_NAME)], check=True) 240 | 241 | except subprocess.CalledProcessError as e: 242 | sys.exit(f'Unpacking discs failed with error {e.returncode}!') 243 | 244 | # Don't trust the user - check for real discs by checking for FAULTY.PSX on sim and STREAM.DAT on arcade 245 | real_arcade_path = None 246 | real_sim_path = None 247 | 248 | if os.path.isfile(os.path.join(arcade_dest, 'STREAM.DAT')): 249 | real_arcade_path = arcade_dest 250 | else: 251 | real_sim_path = arcade_dest 252 | 253 | if os.path.isfile(os.path.join(sim_dest, 'STREAM.DAT')): 254 | real_arcade_path = sim_dest 255 | else: 256 | real_sim_path = sim_dest 257 | 258 | if real_arcade_path is None or real_sim_path is None: 259 | sys.exit('Could not determine the disc types after unpacking! Did you unpack correct Arcade and Simulation discs?') 260 | if real_arcade_path == real_sim_path: 261 | sys.exit('Both discs contain STREAM.DAT! Did you unpack correct Arcade and Simulation discs?') 262 | return real_arcade_path, real_sim_path 263 | 264 | def stepPackDisc(path): 265 | print('Packing the combined disc...') 266 | try: 267 | arguments = [os.path.join(MKPSXISO_PATH, 'mkpsxiso'), os.path.join(path, XML_NAME)] 268 | if not interactive_mode: 269 | arguments.append('-y') 270 | subprocess.run(arguments) 271 | except subprocess.CalledProcessError as e: 272 | sys.exit(f'Packing the disc failed with error {e.returncode}!') 273 | 274 | def stepUnpackVOL(path): 275 | print('Unpacking GT2.VOL from the Simulation Mode disc...') 276 | try: 277 | output_dir = os.path.join(path, 'vol') 278 | subprocess.run([os.path.join(GTVOLTOOL_PATH, "GTVolTool"), '-e2', os.path.join(path, 'GT2.VOL'), output_dir], check=True) 279 | return output_dir 280 | except subprocess.CalledProcessError as e: 281 | sys.exit(f'Unpacking GT2.VOL failed with error {e.returncode}!') 282 | 283 | def stepPackVOL(path, vol_files): 284 | print('Packing GT2.VOL...') 285 | try: 286 | subprocess.run([os.path.join(GTVOLTOOL_PATH, "GTVolTool"), '-r2', vol_files, os.path.join(path, 'GT2.VOL')]) 287 | except subprocess.CalledProcessError as e: 288 | sys.exit(f'Packing GT2.VOL failed with error {e.returncode}!') 289 | 290 | def stepUnpackOVL(path): 291 | print('Unpacking GT2.OVL from the Simulation Mode disc...') 292 | 293 | output_dir = os.path.join(path, 'ovl') 294 | ovl.unpack(os.path.join(path, 'GT2.OVL'), output_dir) 295 | return output_dir 296 | 297 | def stepPackOVL(path, ovl_files): 298 | print('Packing GT2.OVL...') 299 | 300 | files_to_pack = [os.path.join(ovl_files, f'gt2_{(x+1):02}.exe') for x in range(6)] 301 | ovl.pack(files_to_pack, os.path.join(path, 'GT2.OVL')) 302 | 303 | def stepMergeXMLs(arcade_path, sim_path, output_file): 304 | print('Modifying the XML file...') 305 | 306 | arcade_xml = os.path.join(arcade_path, XML_NAME) 307 | sim_xml = os.path.join(sim_path, XML_NAME) 308 | try: 309 | arcade_tree = ET.parse(arcade_xml) 310 | sim_tree = ET.parse(sim_xml) 311 | 312 | arcade_project = arcade_tree.getroot() 313 | sim_project = sim_tree.getroot() 314 | 315 | sim_project.set('image_name', os.path.splitext(output_file)[0] + '.bin') 316 | sim_project.set('cue_sheet', os.path.splitext(output_file)[0] + '.cue') 317 | 318 | if not no_fmvs: 319 | arcade_data_track = arcade_project.find("./track[@type='data']") 320 | sim_data_track = sim_project.find("./track[@type='data']") 321 | 322 | sim_identifiers = sim_data_track.find('identifiers') 323 | sim_identifiers.set('modification_date', DISC_MODIFIED_TIMESTAMP) 324 | 325 | sim_directory_tree = sim_data_track.find('directory_tree') 326 | 327 | arcade_streams = arcade_data_track.find("./directory_tree/file[@source='STREAM.DAT']") 328 | sim_faulty = sim_directory_tree.find("./file[@source='FAULTY.PSX']") 329 | 330 | # STREAMS.DAT needs an absolute path 331 | arcade_streams.set('source', os.path.join(arcade_path, arcade_streams.get('source'))) 332 | 333 | sim_directory_tree.remove(sim_faulty) 334 | sim_directory_tree.append(arcade_streams) 335 | 336 | sim_tree.write(sim_xml) 337 | except ET.ParseError as e: 338 | sys.exit(f'XML parse failure: {e}.') 339 | except (AttributeError, TypeError): # If any of the .find calls return None 340 | sys.exit('XML parse failure.') 341 | 342 | def stepPatchEboot(path): 343 | # If we don't want FMVs, there is nothing to patch in the main executable 344 | if no_fmvs: 345 | return 346 | 347 | print('Patching the boot executable...') 348 | try: 349 | # "Support" all regions by reading SYSTEM.CNF 350 | with open(os.path.join(path, 'SYSTEM.CNF'), 'r') as f: 351 | cnf = {} 352 | for line in f: 353 | key, value = line.split('=', 1) 354 | cnf[key.strip()] = value.strip() 355 | 356 | def removeprefix(string, prefix): 357 | if prefix and string.startswith(prefix): 358 | return string[len(prefix):] 359 | return string 360 | 361 | eboot_name = removeprefix(cnf['BOOT'], 'cdrom:\\').rsplit(';', 1)[0] 362 | with PSEXE(os.path.join(path, eboot_name), readonly=False) as exe: 363 | # Replace li $a0, 1 with 5li $a0, 5 in sub_8005D6E0 to re-enable intro videos 364 | if immediate := getPattern(exe, rb'\x00\x00\x00\x00.{4}\x01\x00\x04\x24\x10\x00\xBF\x8F', 8): # Pointer to \x01 365 | exe.writeU16(immediate, 5) 366 | else: # No matches 367 | raise SetupStepFailedError 368 | 369 | except (OSError, LookupError): 370 | sys.exit('Failed to patch the boot executable!') 371 | except SetupStepFailedError: 372 | sys.exit(f'Failed to locate code patterns in {eboot_name}! Your game version may be unsupported.') 373 | 374 | def stepPatchGT2PlusArcadeOverlay(path): # Semi-temporary until GT2 Plus patches the Arcade overlay on Sim Disc 375 | # Only perform this step if it's GT2+ beta 6.1 for sure. Verify by checking for hashes of Arcade and GT Mode overlays 376 | arcade_overlay_path = os.path.join(path, 'gt2_03.exe') 377 | gtmode_overlay_path = os.path.join(path, 'gt2_05.exe') 378 | try: 379 | with open(arcade_overlay_path, 'rb') as f: 380 | arcade_hash = binascii.crc32(f.read()) & 0xFFFFFFFF 381 | with open(gtmode_overlay_path, 'rb') as f: 382 | gtmode_hash = binascii.crc32(f.read()) & 0xFFFFFFFF 383 | except OSError: 384 | return 385 | 386 | # Compare against hashes of GT2+ beta 6.1 NTSC-U, if they don't match - skip this step 387 | if arcade_hash != 0x660B1AFA or gtmode_hash != 0xD5A011E1: 388 | return 389 | 390 | print('Warning: GT2 Plus beta 6.1 NTSC-U detected - patching a known issue with Peugeot 206 Rally car in the combined Arcade Mode...') 391 | try: 392 | with PSEXE(arcade_overlay_path, readonly=False, headless=True, baseAddress=0x80010000) as exe: 393 | # It's okay to quietly ignore failure here 394 | if peugeot_206_name := getPattern(exe, b'fp2xr\0', 3): 395 | exe.map[exe.addr(peugeot_206_name)] = 0x77 # fp2xr -> fp2wr 396 | except (OSError, LookupError): 397 | optionalStepFailed('Patching GT2 Plus failed!') 398 | 399 | def stepPatchMainMenuOverlay(path): 400 | print('Patching gt2_02.exe (main menu overlay)...') 401 | try: 402 | main_menu_overlay_path = os.path.join(path, 'gt2_02.exe') 403 | data_to_append = bytearray() 404 | with PSEXE(main_menu_overlay_path, readonly=False, headless=True, baseAddress=0x80010000) as exe: 405 | added_data_vaddr_cursor = exe.vaddr(exe.map.size()) 406 | 407 | if menu_actions_process := getPattern(exe, rb'\x00\x00\x00\x00\x07\x00\x62\x2C', 4): 408 | exe.writeU16(menu_actions_process, 8) 409 | 410 | # Get the jump table ptr 411 | menu_actions_jump_table_ptr = exe.readIndirectPtr(menu_actions_process+8, menu_actions_process+12) 412 | # Before writing anything, read the original pointers as needed... 413 | menu_action0_ptr = exe.readAddress(menu_actions_jump_table_ptr) 414 | menu_action_attr_ptr_hi, menu_action_attr_ptr_lo = exe.readU32(menu_action0_ptr+4), exe.readU32(menu_action0_ptr+8) 415 | menu_action_jal = exe.readU32(menu_action0_ptr+24) 416 | menu_action_j = exe.readU32(menu_action0_ptr+32) 417 | 418 | # Now assemble the code 419 | menu_action7 = bytearray() 420 | menu_action7.extend(b'\x02\x00\x04\x24') # li $a0, 2 421 | menu_action7.extend(struct.pack(' 0: 497 | with open(main_menu_overlay_path, 'ab') as f: 498 | f.write(data_to_append) 499 | 500 | except (OSError, LookupError): 501 | sys.exit('Failed to patch gt2_02.exe!') 502 | except SetupStepFailedError: 503 | sys.exit('Failed to locate code patterns in gt2_02.exe! Your game version may be unsupported.') 504 | 505 | def stepPatchRaceOverlay(path): 506 | # If we don't want FMVs, there is nothing to patch in gt2_01.exe 507 | if no_fmvs: 508 | return 509 | 510 | print('Patching gt2_01.exe (race overlay)...') 511 | try: 512 | main_menu_overlay_path = os.path.join(path, 'gt2_01.exe') 513 | with PSEXE(main_menu_overlay_path, readonly=False, headless=True, baseAddress=0x80010000) as exe: 514 | 515 | # Those seem to be related to playing FMVs, but I don't know if it's actually used 516 | # Patching it anyway to match Arcade just in case 517 | if set_s3_to_5 := getPattern(exe, rb'\x10\x00\xB0\xAF\x01\x00\x13\x24', 4): 518 | exe.writeU16(set_s3_to_5, 5) 519 | else: 520 | raise SetupStepFailedError 521 | 522 | if compare_against_v0_1 := getPattern(exe, rb'\x00\x00\x00\x00.{2}\x73\x10'): 523 | # li v0, 1 524 | exe.writeU32(compare_against_v0_1, int.from_bytes(b'\x01\x00\x02\x24', byteorder='little', signed=False)) 525 | # Change beq $v1, $s3 to beq $v1, $v0 526 | exe.writeU16(compare_against_v0_1+6, int.from_bytes(b'\x62\x10', byteorder='little', signed=False)) 527 | else: 528 | raise SetupStepFailedError 529 | 530 | if set_a0_to_0 := getPattern(exe, rb'\x01\x00\x04\x24\x10\x00\xBF\x8F'): 531 | exe.writeU16(set_a0_to_0, 5) 532 | else: 533 | raise SetupStepFailedError 534 | 535 | except (OSError, LookupError): 536 | sys.exit('Failed to patch gt2_01.exe!') 537 | except SetupStepFailedError: 538 | sys.exit('Failed to locate code patterns in gt2_01.exe! Your game version may be unsupported.') 539 | 540 | def stepReplaceVOLFiles(path): 541 | print("Replacing VOL files...") 542 | try: 543 | hashes = {} 544 | # Handle absence of the .hashes file gracefully in case the user removed it 545 | try: 546 | with open(os.path.join(VOL_REPLACEMENTS_PATH, 'file.hashes'), 'r') as f: 547 | for line in f: 548 | value, key = line.split('=', 1) 549 | # Path : Hash dictionary 550 | hashes[os.path.normcase(key.strip())] = int(value.strip(), 16) 551 | except OSError: 552 | print('Warning: file.hashes has been removed or cannot be read.') 553 | 554 | for root, _, files in os.walk(VOL_REPLACEMENTS_PATH): 555 | for file in files: 556 | if file == 'file.hashes': 557 | continue 558 | 559 | copy_file = True 560 | absolute_src_path = os.path.join(root, file) 561 | relative_src_path = os.path.normcase(os.path.relpath(absolute_src_path, VOL_REPLACEMENTS_PATH)) 562 | 563 | absolute_dst_path = os.path.join(path, relative_src_path) 564 | expected_hash = hashes.get(relative_src_path) 565 | if expected_hash is not None: 566 | # If the file is a GZIP file, decompress first as we're interested in CRC32 of the contents, not archive 567 | try: 568 | with gzip.open(absolute_dst_path, 'rb') as f: 569 | actual_hash = binascii.crc32(f.read()) & 0xFFFFFFFF 570 | except gzip.BadGzipFile: 571 | # Try uncompressed 572 | with open(absolute_dst_path, 'rb') as f: 573 | actual_hash = binascii.crc32(f.read()) & 0xFFFFFFFF 574 | 575 | copy_file = expected_hash == actual_hash 576 | 577 | if copy_file: 578 | shutil.copy2(absolute_src_path, absolute_dst_path) 579 | else: 580 | print(f'Warning: {relative_src_path} was not overwritten as it is already modified.') 581 | 582 | except (OSError, SetupStepFailedError, shutil.Error): 583 | sys.exit('Failed to replace VOL files!') 584 | 585 | def patchTXD(path): 586 | with open(path, 'rb') as f: 587 | buf = f.read() 588 | 589 | replacements = [ 590 | # Race strings 591 | (b'in the ARCADE MODE DISC', 29, b'in ARCADE MODE'), 592 | (b'on ARCADE MODE DISC', 29, b'in ARCADE MODE'), 593 | (b'sur le CD du MODE ARCADE', 29, b'dans le MODE ARCADE'), 594 | (b'auf der ARCADE-MODUS-CD', 29, b'im ARCADE-MODUS'), 595 | (b'nel DISCO A MODALIT\xC0 ARCADE', 29, b'nella MODALIT\xC0 ARCADE'), 596 | (b'en el DISCO DE MODO ARCADE', 29, b'en el MODO ARCADE'), 597 | 598 | # Arcade strings 599 | (b'Obtain Licences in Disk 2 to Access All Courses', 59, b'Obtain Licenses in Simulation Mode to Access All Courses'), 600 | (b'Obtain Licences in GT mode to Access All Courses', 59, b'Obtain Licences in GT Mode to Access All Courses'), 601 | (b'Passer permis du CD 2 pour participer aux \xE9preuves', 59, b'Passer les permis du Mode GT pour d\xE9bloquer les circuits'), 602 | (b'Erwerben Sie Lizenzen f\x6Er alle Strecken auf CD 2', 59, b'Erwerben Sie Lizenzen f\x6Er alle Strecken im GT-Modus'), 603 | (b'Ottieni le patenti nel Disco 2 e accedi a tutti i percorsi', 59, b'Ottieni le patenti nella Modalit\xE0 GT e accedi ai percorsi'), 604 | (b'Obtenga carnes del Disco 2 para correr', 59, b'Obtenga carnes en GT Modo para correr') 605 | ] 606 | for replacement in replacements: 607 | search_pattern = replacement[0].ljust(replacement[1], b'\0') 608 | replace_pattern = replacement[2].ljust(replacement[1], b'\0') 609 | if len(search_pattern) > replacement[1] or len(replace_pattern) > replacement[1]: 610 | raise SetupStepFailedError 611 | 612 | buf = buf.replace(search_pattern, replace_pattern, 1) 613 | 614 | with open(path, 'wb') as f: 615 | f.write(buf) 616 | 617 | def stepPatchRaceTXD(path): 618 | print('Patching data-race.txd...') 619 | try: 620 | patchTXD(os.path.join(path, '.text', 'data-race.txd')) 621 | except (OSError, SetupStepFailedError): 622 | optionalStepFailed('Patching data-race.txd failed!') 623 | 624 | def stepPatchArcadeTXD(path): 625 | print('Patching data-arcade.txd inside gt2_03.exe (arcade mode overlay)...') 626 | try: 627 | arcade_overlay_path = os.path.join(path, 'gt2_03.exe') 628 | data_to_append = bytearray() 629 | with PSEXE(arcade_overlay_path, readonly=False, headless=True, baseAddress=0x80010000) as exe: 630 | if data_arcade_gzip_ptr := getPattern(exe, rb'.{2}\x04\x3C.{2}\x84\x24'): 631 | vaddr = exe.readIndirectPtr(data_arcade_gzip_ptr, data_arcade_gzip_ptr+4) 632 | 633 | orig_gzip_location = exe.addr(vaddr) 634 | data, orig_gzip_size, orig_gzip_filename = gzipDecompressBruteforce(exe.map[orig_gzip_location:]) 635 | else: # No matches 636 | raise SetupStepFailedError 637 | 638 | txd_filename = orig_gzip_filename if orig_gzip_filename else 'data-arcade.txd' 639 | txd_path = os.path.join(path, txd_filename) 640 | with open(txd_path, 'wb') as f: 641 | f.write(data) 642 | 643 | patchTXD(txd_path) 644 | 645 | with open(txd_path, 'rb') as f: 646 | data = f.read() 647 | 648 | compressed_data = gzipCompressWithFilename(data, txd_filename) 649 | # If compressed data is larger than the original, try again with filename stripped 650 | if len(compressed_data) > orig_gzip_size: 651 | compressed_data = gzip.compress(data) 652 | 653 | # Wipe the original gzip location before overwriting or appending 654 | exe.map[orig_gzip_location:orig_gzip_location+orig_gzip_size] = b'\0' * orig_gzip_size 655 | if len(compressed_data) > orig_gzip_size: 656 | # Append 657 | vaddr = exe.vaddr(exe.map.size()) 658 | 659 | vaddr = alignByteArray(data_to_append, vaddr, 4) 660 | exe.writeIndirectPtr(data_arcade_gzip_ptr, data_arcade_gzip_ptr+4, vaddr) 661 | data_to_append.extend(compressed_data) 662 | else: 663 | # Replace 664 | exe.map[orig_gzip_location:orig_gzip_location+len(compressed_data)] = compressed_data 665 | 666 | # If there is any data to append, do so 667 | if len(data_to_append) > 0: 668 | with open(arcade_overlay_path, 'ab') as f: 669 | f.write(data_to_append) 670 | 671 | except (OSError, LookupError): 672 | optionalStepFailed('Patching data-arcade.txd inside gt2_03.exe failed!') 673 | except SetupStepFailedError: 674 | optionalStepFailed('Failed to locate code patterns in gt2_03.exe! Your game version may be unsupported.') 675 | 676 | # Those all call sys.exit on failure 677 | arcade_files, sim_files = stepUnpackDiscs() 678 | 679 | vol_files = stepUnpackVOL(sim_files) 680 | ovl_files = stepUnpackOVL(sim_files) 681 | 682 | stepMergeXMLs(arcade_files, sim_files, output_file) 683 | 684 | stepPatchEboot(sim_files) 685 | stepPatchGT2PlusArcadeOverlay(ovl_files) # Semi-temporary until GT2 Plus patches the Arcade overlay on Sim Disc 686 | stepPatchMainMenuOverlay(ovl_files) 687 | stepPatchRaceOverlay(ovl_files) 688 | stepReplaceVOLFiles(vol_files) 689 | 690 | stepPatchRaceTXD(vol_files) # Optional step 691 | stepPatchArcadeTXD(ovl_files) # Optional step 692 | 693 | stepPackOVL(sim_files, ovl_files) 694 | stepPackVOL(sim_files, vol_files) 695 | stepPackDisc(sim_files) 696 | 697 | print('Setup completed successfully!') 698 | 699 | try: 700 | main() 701 | except Exception as e: 702 | eprint(f'{type(e).__name__}: {e}') 703 | except SystemExit as e: 704 | eprint(f'Error: {e}') 705 | 706 | if interactive_mode: 707 | input('\nPress any key to exit...') 708 | --------------------------------------------------------------------------------