├── .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 | [](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 |
--------------------------------------------------------------------------------