├── .gitignore
├── .vscode
└── settings.json
├── GeneralInfo.md
├── README.md
├── blender_addon
├── __init__.py
├── binreader.py
├── lib_run8
│ ├── run8_common.py
│ ├── run8_tilescenery.py
│ └── run8_tr2.py
├── terrain
│ ├── ter.py
│ ├── terrain_utils.py
│ ├── tr2.py
│ ├── tr2_kaitai.py
│ ├── tr3.py
│ └── tr4.py
├── terrain_importer.py
└── utils.py
├── blender_scripts
├── .gitignore
├── README.md
├── autocomplete
│ └── README.md
├── avatar_export.py
├── avatar_import.py
├── binstream.py
├── model_export.py
├── model_import.py
└── terrain_import.py
├── docs
├── README.md
├── TKB.md
├── ai_signal_database.md
├── ai_special_locations.md
├── ai_track_speed_database.md
├── avatar.md
├── common.md
├── key_settings.md
├── old
│ ├── AISignalDatabase.md
│ ├── AISpecialLocations.md
│ ├── AITrackSpeed.md
│ ├── Avatar.md
│ ├── BlockDetectorDatabase.md
│ ├── CarSpewerDatabase.md
│ ├── CommTowerDatabase.md
│ ├── Common.md
│ ├── DefectDetectorList.md
│ ├── DispatcherBlockLightDatabase.md
│ ├── DispatcherSignalControllerDatabase.md
│ ├── DispatcherSwitchIconDatabase.md
│ ├── HornBellConfiguration.md
│ ├── Hump.md
│ ├── HumpControllerList.md
│ ├── IndustryConfiguration.md
│ ├── MilepostDatabase.md
│ ├── Model.md
│ ├── README.md
│ ├── RoadDatabase.md
│ ├── Signal.md
│ ├── Stars4.md
│ ├── TKB.md
│ ├── Terrain.md
│ ├── TrackDatabase.md
│ ├── Traffic.md
│ └── XNG.md
├── service_area_database.md
├── settings.md
├── stars4.md
├── tilescenery.md
├── tr2.md
└── traffic.md
├── lib
└── CS
│ └── Run8
│ ├── .gitignore
│ ├── Installer
│ ├── Environment.wxs
│ ├── Folders.wxs
│ ├── Installer.wixproj
│ ├── Package.en-us.wxl
│ ├── Package.wxs
│ └── assets
│ │ └── License.rtf
│ ├── LibRun8
│ ├── Common
│ │ ├── Class252.cs
│ │ ├── DecalLoader.cs
│ │ ├── DispatcherLight.cs
│ │ ├── Int4.cs
│ │ ├── LightLoader.cs
│ │ ├── Matrix.cs
│ │ ├── ModelObject.cs
│ │ ├── ModelObjectDefinition.cs
│ │ ├── ProceduralVegetation.cs
│ │ ├── Quaternion.cs
│ │ ├── Rectangle.cs
│ │ ├── SceneryAssetLoader.cs
│ │ ├── TileIndex.cs
│ │ ├── Vector2.cs
│ │ ├── Vector3.cs
│ │ ├── Vector4.cs
│ │ └── VertexStruct.cs
│ ├── Formats
│ │ ├── AISignalDatabase.cs
│ │ ├── AITrackSpeedDatabase.cs
│ │ ├── BlockDetectorDatabase.cs
│ │ ├── CarSpewerDatabase.cs
│ │ ├── CommTowerDatabase.cs
│ │ ├── DefectDetector.cs
│ │ ├── DefectDetectorList.cs
│ │ ├── DispatcherLightBlockDatabase.cs
│ │ ├── DispatcherSignalControllerDatabase.cs
│ │ ├── DispatcherSwitchIconDatabase.cs
│ │ ├── FileFormat.cs
│ │ ├── HumpConfigDatabase.cs
│ │ ├── HumpControllerList.cs
│ │ ├── Model.cs
│ │ ├── RoadDatabase.cs
│ │ ├── Signal.cs
│ │ ├── Stars4.cs
│ │ ├── Terrain
│ │ │ ├── Chunk.cs
│ │ │ ├── ChunkStitcher.cs
│ │ │ ├── ETileType.cs
│ │ │ ├── Terrain.cs
│ │ │ ├── TerrainTile.cs
│ │ │ ├── TerrainTileLoadData.cs
│ │ │ ├── Tr2Loader.cs
│ │ │ └── Tr4Loader.cs
│ │ ├── TileScenery.cs
│ │ ├── TrackDatabase.cs
│ │ └── XNG.cs
│ ├── LibRun8.csproj
│ └── Utils
│ │ ├── BinaryReaderExtensions.cs
│ │ ├── BinaryWriterExtensions.cs
│ │ ├── Collada141.cs
│ │ ├── ColladaUtils.cs
│ │ ├── R8String.cs
│ │ ├── Texture.cs
│ │ ├── TileUtil.cs
│ │ └── Utils.cs
│ ├── MappingTest
│ ├── ClassInfo.cs
│ ├── ClassPair.cs
│ ├── Extractor.cs
│ ├── Labeling.cs
│ ├── MappingTest.csproj
│ ├── MethodInfo.cs
│ ├── PairGenerator.cs
│ ├── Program.cs
│ └── Properties
│ │ └── launchSettings.json
│ ├── ModelLoaderTest
│ ├── Class141.cs
│ ├── Class251.cs
│ ├── Class252.cs
│ ├── Class678.cs
│ ├── ModelLoaderTest.csproj
│ ├── Program.cs
│ ├── Properties
│ │ └── launchSettings.json
│ ├── Struct7.cs
│ └── VertexPositionNormalTexture.cs
│ ├── R8Explorer
│ ├── FileFilterManager.cs
│ ├── MainForm.Designer.cs
│ ├── MainForm.cs
│ ├── MainForm.resx
│ ├── Program.cs
│ ├── R8Explorer.csproj
│ └── Run8Version.cs
│ ├── RN8ToObj
│ ├── ColladaConverter.csproj
│ ├── Program.cs
│ └── Properties
│ │ └── launchSettings.json
│ ├── Run8.sln
│ ├── Test
│ ├── Program.cs
│ └── Test.csproj
│ └── TextureTools
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ └── TextureTool.csproj
├── misc
├── README.md
├── ksy
│ ├── README.md
│ ├── compile.bat
│ ├── gen_docs.bat
│ ├── generate_docs.py
│ ├── ksy
│ │ ├── ai_signal_database.ksy
│ │ ├── ai_special_locations.ksy
│ │ ├── ai_track_speed_database.ksy
│ │ ├── avatar.ksy
│ │ ├── common.ksy
│ │ ├── key_settings.ksy
│ │ ├── service_area_database.ksy
│ │ ├── settings.ksy
│ │ ├── stars4.ksy
│ │ ├── tilescenery.ksy
│ │ ├── tr2.ksy
│ │ └── traffic.ksy
│ ├── lib_run8
│ │ ├── kaitai
│ │ │ ├── ai_signal_database.py
│ │ │ ├── ai_special_locations.py
│ │ │ ├── ai_track_speed_database.py
│ │ │ ├── avatar.py
│ │ │ ├── common.py
│ │ │ ├── key_settings.py
│ │ │ ├── service_area_database.py
│ │ │ ├── settings.py
│ │ │ ├── stars4.py
│ │ │ ├── terrain_tr2.py
│ │ │ ├── tile_scenery.py
│ │ │ ├── tr2.py
│ │ │ └── traffic.py
│ │ ├── string_utils.py
│ │ └── visualizer.py
│ └── test.py
├── read_tkb.py
└── terrain_exporter
│ ├── generate_tiles.py
│ ├── index.html
│ ├── rename.py
│ ├── terrain-generator.py
│ └── view.py
└── misc_scripts
├── binreader.py
├── binwriter.py
├── custom_device_reader.py
├── custom_device_writer.py
├── gen_terrain_tr2.py
├── get_latlon_center.py
├── obj_to_rn8.py
├── parse_tr2.py
├── parse_tr4.py
├── skydome_test.py
├── split_geotif.py
├── structs.py
├── structs2.py
├── tr4_to_tr2.py
└── updater.py
/.gitignore:
--------------------------------------------------------------------------------
1 | **/**/Samples/*
2 | __pycache__
3 | *.dae
4 | *.obj
5 | *.rn8
6 | *.r8
7 | *.fbx
8 | *.tr2
9 | *.tr3
10 | *.ter
11 | *.tr4
12 | *.bin
13 | *.tiff
14 | *.tif
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.analysis.extraPaths": [
3 | "./blender_scripts/autocomplete"
4 | ]
5 | }
--------------------------------------------------------------------------------
/GeneralInfo.md:
--------------------------------------------------------------------------------
1 | # Misc Info
2 | Valid up to: `Update9`
3 |
4 | ## Regions
5 | - SouthernCA
6 | - HRS_Southeast
7 | - SelkirkRegion
8 | - NorthernCA
9 | - Pennsylvania
10 |
11 | ## Routes
12 | | Route Name | ID | Region |
13 | | ---------------------- | --- | ---------------------- |
14 | | BNSF_MojaveSub | 100 | SouthernCA |
15 | | BNSF_NeedlesSub | 110 | SouthernCA |
16 | | BNSF_CajonSub | 120 | SouthernCA |
17 | | BNSF_SeligmanSub | 130 | SouthernCA |
18 | | CSX_ALine | 140 | HRS_Southeast |
19 | | BarstowYermo | 150 | SouthernCA |
20 | | CSX_SelkirkTerminal | 170 | SelkirkRegion |
21 | | BNSF_SanBernardinoSub | 200 | SouthernCA |
22 | | CSX_Waycross | 210 | HRS_Southeast |
23 | | CSX_Fitzgerald | 230 | HRS_Southeast |
24 | | CSX_MohawkSub | 240 | SelkirkRegion |
25 | | BNSF_BakersfieldSub | 250 | SouthernCA |
26 | | SP-UP_RosevilleSub | 260 | NorthernCA |
27 | | NS_PittsburghLine_East | 290 | Pennsylvania |
28 | | ArvinOakCreekBranches | 310 | SouthernCA |
29 | | TronaRailway | 320 | SouthernCA |
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Run8 Train Simulator V3 Reverse Engineering
2 |
3 | This repository contains reverse engineered documentation about various Run8 V3 file formats and file parsers. This information is intended for modding.
4 |
5 | [/docs](/docs) - Contains file format specs
6 |
7 | [GeneralInfo.md](/GeneralInfo.md) - Contains misc info such as routes
8 |
9 | [/Run8](/Run8) - C# Library for working with file formats
10 |
11 | [/blender_scripts](/blender_scripts) - Import/Export scripts for Blender 3.x
12 |
13 | ### Progress
14 |
15 | - [ ] AISignalDatabase.r8 (Yes, but low accuracy, will come back to it)
16 | - [ ] AISpecialLocations.r8
17 | - [ ] AITrackSpeedDatabase.r8 (Yes, but low accuracy, will come back to it)
18 | - [x] BlockDetectorDatabase.r8
19 | - [x] CarSpewerDatabase.r8
20 | - [x] CommTowerDatabase.r8
21 | - [ ] DarkSignalDatabase.r8
22 | - [x] DefectDetectorList.r8
23 | - [x] DispatcherBlockLightDatabase.r8
24 | - [x] DispatcherSignalControllerDatabase.r8
25 | - [x] DispatcherSwitchIconDatabase.r8
26 | - [ ] DispatchLabelConfig.r8
27 | - [ ] DispatchNextScreenConfig.r8
28 | - [x] HumpControllerList.r8
29 | - [x] Hump.r8
30 | - [ ] MilepostDatabase.r8
31 | - [ ] RoadDatabase.r8
32 | - [ ] ServiceAreaDatabase.r8
33 | - [ ] SignalHeadDatabase.r8
34 | - [x] TrackDatabase.r8
35 | - [ ] TunnelConfiguration.r8
36 | - [ ] XingDetectorList.r8
37 | - [ ] XingGateDatabase.r8
38 | - [ ] Industry Configuration (.ind)
39 | - [ ] Traffic.r8
40 | - [ ] Tile Scenery (x_y.rn8)
41 | - [ ] Tile Scenery Vegetation (x_y.veg)
42 | - [ ] Terrain Tiles 2 (x_y.tr2)
43 | - [ ] Terrain Tiles 3 (x_y.tr3)
44 | - [ ] Terrain Tiles 4 (x_y.tr4)
45 | - [ ] HornBellConfiguration.r8
46 | - [ ] 3D Model (.rn8) (Partially, implementations are very crude and barely working)
47 | - [ ] Texture (.tx8)
48 | - [ ] Avatars (Partially, implementations are very crude and barely working)
49 | - [x] Shaders/Effects (.tkb)
50 | - .xsb (XACT Sound Bank)
51 | - .xwb (XACT Wave Bank; `unxwb` from http://aluigi.altervista.org/papers.htm)
52 | - [x] Signal (.sig)
53 | - [ ] Run8Settings.r8
54 | - [x] stars4.r8
55 | - [x] Crossing Gate (.xng)
56 | - [ ] Timetable.xnb (Microsoft XNA)
57 | - [ ] .xnb (Microsoft XNA, can apparently store data and images)
58 |
--------------------------------------------------------------------------------
/blender_addon/__init__.py:
--------------------------------------------------------------------------------
1 | # This program is free software; you can redistribute it and/or modify
2 | # it under the terms of the GNU General Public License as published by
3 | # the Free Software Foundation; either version 3 of the License, or
4 | # (at your option) any later version.
5 | #
6 | # This program is distributed in the hope that it will be useful, but
7 | # WITHOUT ANY WARRANTY; without even the implied warranty of
8 | # MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 | # General Public License for more details.
10 | #
11 | # You should have received a copy of the GNU General Public License
12 | # along with this program. If not, see .
13 |
14 | bl_info = {
15 | "name": "io_run8",
16 | "author": "Puyodead1",
17 | "description": "",
18 | "blender": (4, 1, 1),
19 | "version": (0, 0, 1),
20 | "location": "",
21 | "warning": "",
22 | "category": "Generic",
23 | }
24 |
25 | from . import terrain_importer
26 |
27 |
28 | def register():
29 | terrain_importer.register()
30 |
31 |
32 | def unregister():
33 | ...
34 | # terrain_importer.unregister()
35 |
--------------------------------------------------------------------------------
/blender_addon/lib_run8/run8_common.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 |
3 | import kaitaistruct
4 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
5 |
6 |
7 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9):
8 | raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
9 |
10 | class Run8Common(KaitaiStruct):
11 | def __init__(self, _io, _parent=None, _root=None):
12 | self._io = _io
13 | self._parent = _parent
14 | self._root = _root if _root else self
15 | self._read()
16 |
17 | def _read(self):
18 | pass
19 |
20 | class Vector2(KaitaiStruct):
21 | def __init__(self, _io, _parent=None, _root=None):
22 | self._io = _io
23 | self._parent = _parent
24 | self._root = _root if _root else self
25 | self._read()
26 |
27 | def _read(self):
28 | self.x = self._io.read_f4le()
29 | self.y = self._io.read_f4le()
30 |
31 |
32 | class Tilexz(KaitaiStruct):
33 | def __init__(self, _io, _parent=None, _root=None):
34 | self._io = _io
35 | self._parent = _parent
36 | self._root = _root if _root else self
37 | self._read()
38 |
39 | def _read(self):
40 | self.x = self._io.read_s4le()
41 | self.z = self._io.read_s4le()
42 |
43 |
44 | class CsString(KaitaiStruct):
45 | def __init__(self, _io, _parent=None, _root=None):
46 | self._io = _io
47 | self._parent = _parent
48 | self._root = _root if _root else self
49 | self._read()
50 |
51 | def _read(self):
52 | self.len = self._io.read_u1()
53 | self.value = (self._io.read_bytes(self.len)).decode(u"UTF-8")
54 |
55 |
56 | class Matrix4(KaitaiStruct):
57 | def __init__(self, _io, _parent=None, _root=None):
58 | self._io = _io
59 | self._parent = _parent
60 | self._root = _root if _root else self
61 | self._read()
62 |
63 | def _read(self):
64 | self.m11 = self._io.read_f4le()
65 | self.m12 = self._io.read_f4le()
66 | self.m13 = self._io.read_f4le()
67 | self.m14 = self._io.read_f4le()
68 | self.m21 = self._io.read_f4le()
69 | self.m22 = self._io.read_f4le()
70 | self.m23 = self._io.read_f4le()
71 | self.m24 = self._io.read_f4le()
72 | self.m31 = self._io.read_f4le()
73 | self.m32 = self._io.read_f4le()
74 | self.m33 = self._io.read_f4le()
75 | self.m34 = self._io.read_f4le()
76 | self.m41 = self._io.read_f4le()
77 | self.m42 = self._io.read_f4le()
78 | self.m43 = self._io.read_f4le()
79 | self.m44 = self._io.read_f4le()
80 |
81 |
82 | class Vector3(KaitaiStruct):
83 | def __init__(self, _io, _parent=None, _root=None):
84 | self._io = _io
85 | self._parent = _parent
86 | self._root = _root if _root else self
87 | self._read()
88 |
89 | def _read(self):
90 | self.x = self._io.read_f4le()
91 | self.y = self._io.read_f4le()
92 | self.z = self._io.read_f4le()
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/blender_addon/lib_run8/run8_tilescenery.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 |
3 | import kaitaistruct
4 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
5 | from .run8_common import Run8Common
6 |
7 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9):
8 | raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
9 |
10 | class Run8Tilescenery(KaitaiStruct):
11 | def __init__(self, _io, _parent=None, _root=None):
12 | self._io = _io
13 | self._parent = _parent
14 | self._root = _root if _root else self
15 | self._read()
16 |
17 | def _read(self):
18 | self.num_assets = self._io.read_s4le()
19 | self.assets = []
20 | for i in range(self.num_assets):
21 | self.assets.append(Run8Tilescenery.Asset(self._io, self, self._root))
22 |
23 |
24 | class Asset(KaitaiStruct):
25 | def __init__(self, _io, _parent=None, _root=None):
26 | self._io = _io
27 | self._parent = _parent
28 | self._root = _root if _root else self
29 | self._read()
30 |
31 | def _read(self):
32 | self.num_decals = self._io.read_s4le()
33 | self.decals = []
34 | for i in range(self.num_decals):
35 | self.decals.append(Run8Tilescenery.Decal(self._io, self, self._root))
36 |
37 | self.disregard_bounding_test = self._io.read_bits_int_be(1) != 0
38 | self._io.align_to_byte()
39 | self.model_name = Run8Common.CsString(self._io, self, self._root)
40 | self.position = Run8Common.Vector3(self._io, self, self._root)
41 | self.rotation = Run8Common.Vector3(self._io, self, self._root)
42 | self.scale = Run8Common.Vector3(self._io, self, self._root)
43 | self.tile_xz = Run8Common.Tilexz(self._io, self, self._root)
44 |
45 |
46 | class Decal(KaitaiStruct):
47 | def __init__(self, _io, _parent=None, _root=None):
48 | self._io = _io
49 | self._parent = _parent
50 | self._root = _root if _root else self
51 | self._read()
52 |
53 | def _read(self):
54 | self.color_r = self._io.read_f4le()
55 | self.color_g = self._io.read_f4le()
56 | self.color_b = self._io.read_f4le()
57 | self.num_digits = self._io.read_s4le()
58 | self.digits = []
59 | for i in range(self.num_digits):
60 | self.digits.append(Run8Tilescenery.Digit(self._io, self, self._root))
61 |
62 | self.offset = Run8Common.Vector3(self._io, self, self._root)
63 | self.rotation_deg = Run8Common.Vector3(self._io, self, self._root)
64 | self.size = self._io.read_f4le()
65 | self.texture_name = Run8Common.CsString(self._io, self, self._root)
66 |
67 |
68 | class Digit(KaitaiStruct):
69 | def __init__(self, _io, _parent=None, _root=None):
70 | self._io = _io
71 | self._parent = _parent
72 | self._root = _root if _root else self
73 | self._read()
74 |
75 | def _read(self):
76 | self.digit = self._io.read_s4le()
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/blender_addon/lib_run8/run8_tr2.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 |
3 | from typing import List
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from .run8_common import Run8Common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 9):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.9 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class Run8Tr2(KaitaiStruct):
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.texture_1 = Run8Common.CsString(self._io, self, self._root)
21 | self.texture_2 = Run8Common.CsString(self._io, self, self._root)
22 | self.texture_3 = Run8Common.CsString(self._io, self, self._root)
23 | self.texture_4 = Run8Common.CsString(self._io, self, self._root)
24 | self.chunks: List[Run8Tr2.ChunkRow] = []
25 | for i in range(25):
26 | self.chunks.append(Run8Tr2.ChunkRow(self._io, self, self._root))
27 |
28 | self.lon_east = self._io.read_f4le()
29 | self.lon_west = self._io.read_f4le()
30 | self.lat_north = self._io.read_f4le()
31 | self.lat_south = self._io.read_f4le()
32 |
33 | class ChunkRow(KaitaiStruct):
34 | def __init__(self, _io, _parent=None, _root=None):
35 | self._io = _io
36 | self._parent = _parent
37 | self._root = _root if _root else self
38 | self._read()
39 |
40 | def _read(self):
41 | self.chunks: List[Run8Tr2.Chunk] = []
42 | for i in range(25):
43 | self.chunks.append(Run8Tr2.Chunk(self._io, self, self._root))
44 |
45 |
46 |
47 | class Chunk(KaitaiStruct):
48 | def __init__(self, _io, _parent=None, _root=None):
49 | self._io = _io
50 | self._parent = _parent
51 | self._root = _root if _root else self
52 | self._read()
53 |
54 | def _read(self):
55 | self.chunk_size = self._io.read_u4le()
56 | self.elevations: List[Run8Tr2.ElevationCol] = []
57 | for i in range(self.chunk_size):
58 | self.elevations.append(Run8Tr2.ElevationCol(self._io, self, self._root))
59 |
60 |
61 |
62 | class ElevationCol(KaitaiStruct):
63 | def __init__(self, _io, _parent=None, _root=None):
64 | self._io = _io
65 | self._parent = _parent
66 | self._root = _root if _root else self
67 | self._read()
68 |
69 | def _read(self):
70 | self.elevation: List[float] = []
71 | for i in range(self._parent.chunk_size):
72 | self.elevation.append(self._io.read_f4le())
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/blender_addon/terrain/ter.py:
--------------------------------------------------------------------------------
1 | from ..binreader import BinaryReader
2 | from .terrain_utils import ETileType, TerrainTile
3 |
4 |
5 | class TER(TerrainTile):
6 | def __init__(self, reader: BinaryReader, x: float, y: float) -> None:
7 | super().__init__(reader, ETileType.TER, x, y)
8 |
9 | self.read()
10 |
11 | def read(self):
12 | pass
13 |
--------------------------------------------------------------------------------
/blender_addon/terrain/tr3.py:
--------------------------------------------------------------------------------
1 | from ..binreader import BinaryReader
2 | from .terrain_utils import ETileType, TerrainTile
3 |
4 |
5 | class TR3(TerrainTile):
6 | def __init__(self, reader: BinaryReader, x: float, y: float) -> None:
7 | super().__init__(reader, ETileType.TR3, x, y)
8 |
9 | self.read()
10 |
11 | def read(self):
12 | pass
13 |
--------------------------------------------------------------------------------
/blender_addon/terrain/tr4.py:
--------------------------------------------------------------------------------
1 | from ..binreader import BinaryReader
2 | from .terrain_utils import ETileType, TerrainTile
3 |
4 |
5 | class TR4(TerrainTile):
6 | def __init__(self, reader: BinaryReader, x: float, y: float) -> None:
7 | super().__init__(reader, ETileType.TR4, x, y)
8 |
9 | self.read()
10 |
11 | def read(self):
12 | pass
13 |
--------------------------------------------------------------------------------
/blender_addon/terrain_importer.py:
--------------------------------------------------------------------------------
1 | import bpy
2 | from bpy.props import StringProperty
3 | from bpy.types import Operator
4 | from bpy_extras.io_utils import ImportHelper
5 |
6 | from .binreader import BinaryReader
7 | from .terrain.ter import TER
8 | from .terrain.tr2 import TR2
9 | from .terrain.tr2_kaitai import TR2Kaitai
10 | from .terrain.tr3 import TR3
11 | from .terrain.tr4 import TR4
12 |
13 |
14 | def import_model(context, filepath):
15 | print("\n" * 10)
16 | print("Importing Run8 Terrain Tile: %r..." % (filepath))
17 |
18 | with open(filepath, "rb") as f:
19 | reader = BinaryReader(f)
20 | split = filepath.split("\\")[-1].split("_")
21 | x = int(split[0])
22 | y = int(split[1].split(".")[0])
23 |
24 | if filepath.endswith(".ter"):
25 | tile = TER(reader, x, y)
26 | elif filepath.endswith(".tr2"):
27 | # tile = TR2(reader, x, y)
28 | tile = TR2Kaitai(filepath, x, y)
29 | elif filepath.endswith(".tr3"):
30 | tile = TR3(reader, x, y)
31 | elif filepath.endswith(".tr4"):
32 | tile = TR4(reader, x, y)
33 | else:
34 | raise Exception("Unknown file type")
35 |
36 | tile.draw()
37 |
38 | return {"FINISHED"}
39 |
40 |
41 | class ImportRun8TerrainTile(Operator, ImportHelper):
42 | bl_idname = "io_run8.import_terrain_tile"
43 | bl_label = "Import Terrain Tile"
44 |
45 | filter_glob: StringProperty(
46 | default="*.tr2;*.tr2;*.tr4;*.ter",
47 | options={"HIDDEN"},
48 | maxlen=255, # Max internal buffer length, longer would be clamped.
49 | ) # type: ignore
50 |
51 | def execute(self, context):
52 | return import_model(context, self.filepath)
53 |
54 |
55 | def run8_terrain_menu_func_import(self, context):
56 | self.layout.operator(ImportRun8TerrainTile.bl_idname, text="Run8 Terrain Tile (.tr2/.tr3/.tr4/.ter)")
57 |
58 |
59 | def register():
60 | bpy.utils.register_class(ImportRun8TerrainTile)
61 |
62 | # prevent duplicate menu entries
63 | if hasattr(bpy.types.TOPBAR_MT_file_import.draw, "_draw_funcs"):
64 | if run8_terrain_menu_func_import.__name__ not in (
65 | f.__name__ for f in bpy.types.TOPBAR_MT_file_import.draw._draw_funcs
66 | ):
67 | bpy.types.TOPBAR_MT_file_import.append(run8_terrain_menu_func_import)
68 | else:
69 | bpy.types.TOPBAR_MT_file_import.append(run8_terrain_menu_func_import)
70 |
71 |
72 | def unregister():
73 | clazz = bpy.types.NodeTree.bl_rna_get_subclass_py("io_run8.import_terrain_tile")
74 | bpy.utils.unregister_class(clazz)
75 | bpy.types.TOPBAR_MT_file_import.remove(run8_terrain_menu_func_import)
76 |
--------------------------------------------------------------------------------
/blender_addon/utils.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | import mathutils
4 |
5 |
6 | class Vertex(object):
7 | position: mathutils.Vector = None
8 | normal: mathutils.Vector = None
9 | uv: mathutils.Vector = None
10 |
11 | def to_json(self) -> dict:
12 | return {"position": self.position.to_tuple(), "normal": self.normal.to_tuple(), "uv": self.uv.to_tuple()}
13 |
14 | def __str__(self) -> str:
15 | return json.dumps(self.to_json())
16 |
--------------------------------------------------------------------------------
/blender_scripts/.gitignore:
--------------------------------------------------------------------------------
1 | autocomplete/*
2 | !autocomplete/README.md
--------------------------------------------------------------------------------
/blender_scripts/README.md:
--------------------------------------------------------------------------------
1 | import/export scripts for blender, these would be made into an `io_scene_run8` addon at some point.
2 |
3 | I cannot for the life of me get skeleton import working for avatars.
4 |
5 | currently includes:
6 | - Avatars
7 | - Mesh Import
8 | - Mesh Export (Game crashes, skeleton and animations are required)
9 | - Railcar Models
10 | - Mesh Import
--------------------------------------------------------------------------------
/blender_scripts/autocomplete/README.md:
--------------------------------------------------------------------------------
1 | You can get this from https://github.com/Korchy/blender_autocomplete/tree/master/3.4
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | New style of file format specs, 99% of these are autogenerated from the .ksy files
2 |
--------------------------------------------------------------------------------
/docs/TKB.md:
--------------------------------------------------------------------------------
1 | # Shader File (.tkb)
2 |
3 | These files are from SharpDX, they are compiled shaders/effects. I am not going to write a dedicated tool for these as they're a pain in the ass (for me at least) and the compiler already has the ability to dump the bytecode.
4 |
5 | ## Dump Bytecode
6 |
7 | You will need to get `tkfxc.exe` from SharpDX, rather then having to compile it, you can just get it precompiled from Nuget: https://www.nuget.org/api/v2/package/SharpDX/2.6.3. This will download `sharpdx.2.6.3.nupkg` which is just a zip file, you can either change the file extension from `.nupkg` to `.zip` or just open it with 7zip (or any other archive program really). The binary can be found in at `sharpdx.2.6.3\Bin\DirectX11_2-net40\tkfxc.exe`.
8 |
9 | Now you can just run:
10 |
11 | - `tkfxc.exe > bytecode.txt`
12 |
--------------------------------------------------------------------------------
/docs/ai_signal_database.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # AISignalDatabase (AISignalDatabase.r8)
4 |
5 | Contains a list of AI Signals
6 |
7 | ## Root Structure
8 |
9 | | Type | ID | Description |
10 | | ---------- | ---- | ----------- |
11 | | Int32 | reserved | This field is unused |
12 | | Int32 | num_entries | |
13 | | ai_signal[] | entries | |
14 |
15 |
16 | ## Types
17 |
18 | ### ai_signal
19 |
20 | | Type | ID | Description |
21 | | ---------- | ---- | ----------- |
22 | | Int32 | reserved | This field is unused |
23 | | Int32 | num_entries | |
24 | | Int32[] | entries | |
25 | | Boolean | bool1 | |
26 | | Int32 | int1 | |
27 | | Int32 | int2 | |
28 | | Boolean | bool2 | |
29 | | class_341 | class_341_11 | |
30 | | Boolean | bool3 | |
31 | | class_341 | class_341_22 | |
32 |
33 | - 1: Only if bool2 is true
34 | - 2: Only if bool3 is true
35 |
36 | ### class_341
37 |
38 | | Type | ID | Description |
39 | | ---------- | ---- | ----------- |
40 | | Int32 | int1 | |
41 | | Int32 | int2 | |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/docs/ai_special_locations.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # AISpecialLocations (AISpecialLocations.r8)
4 |
5 | Contains a list of AI Special Locations
6 |
7 | ## Root Structure
8 |
9 | | Type | ID | Description |
10 | | ---------- | ---- | ----------- |
11 | | Int32 | reserved | This field is unused |
12 | | Int32 | num_entries | |
13 | | ai_special_location[] | entries | |
14 |
15 |
16 | ## Types
17 |
18 | ### ai_special_location
19 |
20 | | Type | ID | Description |
21 | | ---------- | ---- | ----------- |
22 | | Int32 | reserved | This field is unused |
23 | | [R8String](common.md#r8string) | name | |
24 | | UInt8 ([ai_special_location_type](#enums)) | type | |
25 | | Int32 | int1 | |
26 | | Int32 | int2 | |
27 | | Int32 | int3 | |
28 | | Float | float1 | |
29 | | Int32 | int4 | |
30 | | Boolean | bool1 | |
31 |
32 |
33 | ## Enums
34 | ### ai_special_location_type
35 |
36 | | Value | Name |
37 | | ------- | ------ |
38 | | spawn_point | 0 |
39 | | crew_change | 1 |
40 | | crew_change_and_hold | 2 |
41 | | passenger | 3 |
42 | | passenger_crew_change | 4 |
43 | | passenger_crew_change_and_hold | 5 |
44 | | reliquish | 6 |
45 | | passenger_reliquish | 7 |
46 |
47 |
--------------------------------------------------------------------------------
/docs/ai_track_speed_database.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # AITrackSpeedDatabase (AITrackSpeedDatabase.r8)
4 |
5 | Contains a list of AI Track Speeds
6 |
7 | ## Root Structure
8 |
9 | | Type | ID | Description |
10 | | ---------- | ---- | ----------- |
11 | | Int32 | reserved | This field is unused |
12 | | Int32 | num_entries | |
13 | | ai_track_speed[] | entries | |
14 |
15 |
16 | ## Types
17 |
18 | ### ai_track_speed
19 |
20 | | Type | ID | Description |
21 | | ---------- | ---- | ----------- |
22 | | Int32 | reserved | This field is unused |
23 | | Int32 | int1 | |
24 | | Int32 | num_entries | |
25 | | class_322[] | entries | |
26 |
27 |
28 | ### class_322
29 |
30 | | Type | ID | Description |
31 | | ---------- | ---- | ----------- |
32 | | Int32 | reserved | This field is unused |
33 | | Int32 | int1 | |
34 | | Int32 | int2 | |
35 | | Int32 | int3 | |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/docs/avatar.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Avatar File
4 |
5 | There are currently 3 avatars:
6 | - Brian
7 | - Chris
8 | - Pablo
9 |
10 |
11 | Avatar files are 3D model files with the `rn8` file extension. Model units are in centimeters.
12 |
13 | ## Root Structure
14 |
15 | | Type | ID | Description |
16 | | ---------- | ---- | ----------- |
17 | | Int32 | vertex_count | Divide by 7 |
18 | | vertex_struct[] | vertices | |
19 | | Int32 | texture_count | Add 6 |
20 | | [C# String](common.md#cs_string)[] | textures | |
21 | | Boolean | is_ushort_index_buffer | True if the indices are stored as ushorts |
22 | | Int32 | num_index_buffer | |
23 | | UShort[] | ushort_index_buffer1 | |
24 | | Int32[] | index_buffer2 | |
25 | | Int32 | num_unknown_structs | Subtract 9 |
26 | | unknown_struct[] | unknown_structs | |
27 | | Int32 | num_skeleton_hierarchy | |
28 | | Int32[] | skeleton_hierarchy | |
29 | | Int32 | num_bone_indices | |
30 | | bone_index_struct[] | bone_indices | |
31 | | Int32 | num_bind_poses | |
32 | | [Matrix4x4](common.md#matrix4)[] | bind_poses | |
33 | | Int32 | num_inverse_bind_poses | |
34 | | [Matrix4x4](common.md#matrix4)[] | inverse_bind_poses | |
35 | | Int32 | num_animations | Seems to always be 16 |
36 | | animation_clip[] | animations | |
37 |
38 | - 1: Only if the index buffer is ushort
39 | - 2: Only if the index buffer is not ushort
40 |
41 | ## Types
42 |
43 | ### vertex_struct
44 |
45 | | Type | ID | Description |
46 | | ---------- | ---- | ----------- |
47 | | Float | reserved1 | |
48 | | Float | position_x | Multiply by 63.7f |
49 | | Float | normal_y | Divide by -1.732f |
50 | | Float | position_z | Divide by 16f |
51 | | Float | tex_coord_x | Divide by 4.8f |
52 | | Float | normal_x | Divide by 10.962f |
53 | | Float | reserved2 | |
54 | | Float | normal_z | Divide by 11.432f |
55 | | Float | tex_coord_y | Divide by 9.6f |
56 | | Float | position_y | Multiply by 6f |
57 | | UInt8 | blend_index_w | |
58 | | Float | blend_weight_z | |
59 | | UInt8 | blend_index_x | |
60 | | Float | blend_weight_y | |
61 | | UInt8 | blend_index_y | |
62 | | Float | blend_weight_w | |
63 | | UInt8 | blend_idex_z | |
64 | | Float | blend_weight_x | |
65 |
66 |
67 | ### unknown_struct
68 |
69 | | Type | ID | Description |
70 | | ---------- | ---- | ----------- |
71 | | Int32 | reserved | This field is unused |
72 | | Int32 | texture_index1 | |
73 | | Int32 | num_index_buffer | |
74 | | Int32 | start_index_location | |
75 | | Int32 | base_vertex_location | |
76 |
77 | - 1: `_mrao` is appended to the texture name
78 |
79 | ### bone_index_struct
80 |
81 | | Type | ID | Description |
82 | | ---------- | ---- | ----------- |
83 | | [C# String](common.md#cs_string) | key | |
84 | | Int32 | bone_index | |
85 |
86 |
87 | ### animation_clip
88 |
89 | | Type | ID | Description |
90 | | ---------- | ---- | ----------- |
91 | | [C# String](common.md#cs_string) | clip_name | |
92 | | Double | duration | Duration in ms |
93 | | Int32 | num_keyframes | |
94 | | animation_keyframe[] | keyframes | |
95 |
96 |
97 | ### animation_keyframe
98 |
99 | | Type | ID | Description |
100 | | ---------- | ---- | ----------- |
101 | | Int32 | bone_index | |
102 | | Double | time | |
103 | | [Matrix4x4](common.md#matrix4) | transform | |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/docs/common.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Common
4 |
5 | Common Types
6 |
7 | ## Encoding Strings
8 | ```c#
9 | string s = "1ST COAST RECYCLING";
10 | byte[] bytes = Encoding.UTF8.GetBytes(s);
11 | byte[] encoded = new byte[bytes.Length * 2];
12 | int num = 0;
13 | for (int i = 0; i < bytes.Length; i++)
14 | {
15 | encoded[num++] = (byte)(bytes[i] >> 4);
16 | encoded[num++] = (byte)(bytes[i] << 4);
17 | }
18 | ```
19 |
20 | ## Decoding Strings
21 | ```c#
22 | byte[] encoded = ;
23 | byte[] decodedBytes = new byte[encoded.Length / 2];
24 | int num = 0;
25 | for (int i = 0; i < decodedBytes.Length; i++)
26 | {
27 | decodedBytes[i] |= (byte)(encoded[num++] << 4);
28 | decodedBytes[i] |= (byte)(encoded[num++] >> 4);
29 | }
30 |
31 | string decodedString = Encoding.UTF8.GetString(decodedBytes);
32 | ```
33 |
34 | ## Types
35 |
36 | ### r8string
37 |
38 | Run8 specific string format
39 |
40 | | Type | ID | Description |
41 | | ---------- | ---- | ----------- |
42 | | Int32 | len_value | Length of the encoded string, x2 len of decoded string |
43 | | Bytes | value | Decoded string |
44 |
45 |
46 | ### cs_string
47 |
48 | C# style string
49 |
50 | | Type | ID | Description |
51 | | ---------- | ---- | ----------- |
52 | | UInt8 | len | Length of the string as a 7 bit encoded int |
53 | | String | value | |
54 |
55 |
56 | ### vector2
57 |
58 | | Type | ID | Description |
59 | | ---------- | ---- | ----------- |
60 | | Float | x | |
61 | | Float | y | |
62 |
63 |
64 | ### vector3
65 |
66 | | Type | ID | Description |
67 | | ---------- | ---- | ----------- |
68 | | Float | x | |
69 | | Float | y | |
70 | | Float | z | |
71 |
72 |
73 | ### tilexz
74 |
75 | | Type | ID | Description |
76 | | ---------- | ---- | ----------- |
77 | | Int32 | x | |
78 | | Int32 | z | |
79 |
80 |
81 | ### matrix4
82 |
83 | | Type | ID | Description |
84 | | ---------- | ---- | ----------- |
85 | | Float | m11 | |
86 | | Float | m12 | |
87 | | Float | m13 | |
88 | | Float | m14 | |
89 | | Float | m21 | |
90 | | Float | m22 | |
91 | | Float | m23 | |
92 | | Float | m24 | |
93 | | Float | m31 | |
94 | | Float | m32 | |
95 | | Float | m33 | |
96 | | Float | m34 | |
97 | | Float | m41 | |
98 | | Float | m42 | |
99 | | Float | m43 | |
100 | | Float | m44 | |
101 |
102 |
103 | ### color
104 |
105 | | Type | ID | Description |
106 | | ---------- | ---- | ----------- |
107 | | UInt8 | a | |
108 | | UInt8 | r | |
109 | | UInt8 | g | |
110 | | UInt8 | b | |
111 |
112 |
113 | ### boolean
114 |
115 | This is just a bullshit stub
116 |
117 | | Type | ID | Description |
118 | | ---------- | ---- | ----------- |
119 | | UInt8 | value | |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/docs/key_settings.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Key Settings (Run8KeySettings.r8)
4 |
5 | Stores game keybind settings
6 |
7 | ## Root Structure
8 |
9 | | Type | ID | Description |
10 | | ---------- | ---- | ----------- |
11 | | Int32 | reserved | This field is unused |
12 | | Int32 | num_settings | |
13 | | key_setting[] | settings | |
14 |
15 |
16 | ## Types
17 |
18 | ### key_setting
19 |
20 | | Type | ID | Description |
21 | | ---------- | ---- | ----------- |
22 | | Int32 | reserved | This field is unused |
23 | | [R8String](common.md#r8string) | name | |
24 | | Int8 | enum70 | |
25 | | Int32 | num_keys | |
26 | | Int32[] | keys | |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/docs/old/AISignalDatabase.md:
--------------------------------------------------------------------------------
1 | # AI Signal Database (AISignalDatabase.r8)
2 |
3 | Contains a list of signals and their information
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------- | -------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | AISignal Count |
11 | | 8 | AISignal | AISignals |
12 |
13 | ## AISignal
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | -------- | ----------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | Int32 | Unknown |
19 | | 8 | Unknown1 | Unknown1 |
20 | | ... | Byte | Unknown Boolean |
21 | | ... | Int32 | Unknown |
22 | | ... | Int32 | Unknown |
23 | | ... | Byte | Unknown Boolean n |
24 | | ... | Unknown2 | Unknown2 (if n) |
25 | | ... | Byte | Unknown Boolean m |
26 | | ... | Unknown2 | Unknown2 (if m) |
27 |
28 | ## Unknown1
29 |
30 | | Offset | Type | Explaination |
31 | | ------ | ----- | ------------ |
32 | | 0 | Int32 | Unknown |
33 |
34 | ## Unknown2
35 |
36 | | Offset | Type | Explaination |
37 | | ------ | ----- | ------------ |
38 | | 0 | Int32 | Unknown |
39 | | 4 | Int32 | Unknown |
40 |
--------------------------------------------------------------------------------
/docs/old/AISpecialLocations.md:
--------------------------------------------------------------------------------
1 | # AI Special Locations (AISpecialLocations.r8)
2 |
3 | Seems to contain information about "special" track locations.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----------------- | ----------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | AISpecialLocation Count |
11 | | 8 | AISpecialLocation | AISpecialLocation |
12 |
13 | ## AISpecialLocation
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | -------- | ------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | R8String | Location Name |
19 | | ... | Byte | SpecialLocationType |
20 | | ... | Int32 | Unknown |
21 | | ... | Int32 | Unknown |
22 | | ... | Int32 | Unknown |
23 | | ... | Float | Unknown |
24 | | ... | Int32 | Unknown |
25 | | ... | Byte | Unknown Boolean |
26 |
27 | ## SpecialLocationType
28 |
29 | | Key | Value |
30 | | --- | -------------------------- |
31 | | 0 | SpawnPoint |
32 | | 1 | CrewChange |
33 | | 2 | CrewChangeAndHold |
34 | | 3 | Passenger |
35 | | 4 | PassengerCrewChange |
36 | | 5 | PassengerCrewChangeAndHold |
37 | | 6 | Relinquish |
38 | | 7 | PassengerRelinquish |
39 |
--------------------------------------------------------------------------------
/docs/old/AITrackSpeed.md:
--------------------------------------------------------------------------------
1 | # AI Track Speed (AITrackSpeed.r8)
2 |
3 | Seems to contain information related to track speeds
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----- | ------------ |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Entry count |
11 | | 8 | Entry | Entries |
12 |
13 | ## Entry
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | -------- | -------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | Int32 | Unknown |
19 | | 8 | Int32 | Unknown1 Count |
20 | | 12 | Unknown1 | Unknown1s |
21 |
22 | ## Unknown1
23 |
24 | | Offset | Type | Explaination |
25 | | ------ | ----- | ------------ |
26 | | 0 | Int32 | Reserved |
27 | | 4 | Int32 | Unknown |
28 | | 8 | Int32 | Unknown |
29 | | 12 | Int32 | Unknown |
30 |
--------------------------------------------------------------------------------
/docs/old/Avatar.md:
--------------------------------------------------------------------------------
1 | # Avatar
2 |
3 | There are currently 3 avatars:
4 |
5 | - Brian
6 | - Chris
7 | - Pablo
8 |
9 | Avatar files are 3D model files with the `rn8` file extension. Models are in cm
10 |
11 | ## Header
12 |
13 | | Offset | Type | Explaination |
14 | | ------ | ----------------- | ------------------------------ |
15 | | 0 | Int32 | VertexStruct Count1 |
16 | | 4 | VertexStruct[] | VertexStructs |
17 | | ... | Int32 | Texture Name Count2 |
18 | | ... | String[] | Texture Names |
19 | | ... | Bool | IsUshortBuffer |
20 | | ... | Int32 | Index Buffer Size |
21 | | ... | Int32[] | Index Buffer |
22 | | ... | Int32 | Unknown1 Count3 |
23 | | ... | UnknownStruct1 | UnknownStruct1s4 |
24 | | ... | Int32 | Skeleton Hierarchy Count |
25 | | ... | Int32[] | Skeleton Hierarchy |
26 | | ... | Int32 | Bone Index Count |
27 | | ... | BoneIndexStruct[] | Bone Indices |
28 | | ... | Int32 | Bind Pose Count |
29 | | ... | Matrix4x4[] | Bind Poses |
30 | | ... | Int32 | Inverse Bind Pose Count |
31 | | ... | Matrix4x4[] | Inverse Bind Poses |
32 | | ... | Int32 | Animation Clip Count |
33 | | ... | AnimationClip[] | Animation Clips |
34 |
35 | - 1: This number gets divided by 7
36 | - 2: 6 is added to the number
37 | - 3: 9 is subtracted from the number
38 | - 4: These are only read when the count is not 0, otherwise only a single entry is created
39 |
40 | ## UnknownStruct1
41 |
42 | | Offset | Type | Explaination | Value If Single |
43 | | ------ | ----- | ------------------------- | ----------------- |
44 | | 0 | Int32 | Reserved | |
45 | | 4 | Int32 | Texture Index1 | |
46 | | 8 | Int32 | Index Count | Index Buffer Size |
47 | | 12 | Int32 | Start Index Location | 0 |
48 | | 16 | Int32 | Base Vertex Location | 0 |
49 |
50 | - 1: Gets the texture at the index and appends `_mrao`
51 |
52 | ## BoneIndexStruct
53 |
54 | | Offset | Type | Explaination |
55 | | ------ | ------ | ------------ |
56 | | 0 | String | Key |
57 | | ... | Int32 | Bone Index |
58 |
59 | ## AnimationClip
60 |
61 | | Offset | Type | Explaination |
62 | | ------ | ---------- | -------------- |
63 | | 0 | String | Key |
64 | | ... | Double | Duration (ms) |
65 | | ... | Int32 | Keyframe Count |
66 | | ... | Keyframe[] | Keyframes |
67 |
68 | ## Keyframe
69 |
70 | | Offset | Type | Explaination |
71 | | ------ | --------- | ------------ |
72 | | 0 | Int32 | Bone |
73 | | 4 | Double | Time (ms) |
74 | | 12 | Matrix4x4 | Transform |
75 |
--------------------------------------------------------------------------------
/docs/old/BlockDetectorDatabase.md:
--------------------------------------------------------------------------------
1 | # BlockDetectorDatabase (BlockDetectorDatabase.r8)
2 |
3 | Contains information for Block Detectors.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ------------- | -------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Detector Count |
11 | | 8 | BlockDetector | Detectors |
12 |
13 | ## Block Detector
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | ---------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | Int32 | Index |
19 | | 8 | Int32 | Number of Tracks |
20 | | 12 | Int32[] | Track Indices |
21 | | ... | TileIndex | Tile XZ |
22 | | ... | Vector3 | Position |
23 |
--------------------------------------------------------------------------------
/docs/old/CarSpewerDatabase.md:
--------------------------------------------------------------------------------
1 | # CarSpewerDatabase (CarSpewerDatabase.r8)
2 |
3 | Contains information for Car Spewers (Spawners)
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----------- | ----------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Spewers |
11 | | 8 | CarSpewer[] | Spewers |
12 |
13 | ## Car Spewer
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | ----------------- | -------------------------- |
17 | | 0 | Int32 | Unknown (num) |
18 | | 4 | Int32 | Unknown (Not used) |
19 | | 8 | Int32 | Road Node Index |
20 | | 12 | Int32 | Max Cars |
21 | | 16 | Int32 | Min Time between Spews |
22 | | 20 | Int32 | Max Time between Spews |
23 | | 24 | Float | Max Speed (Only if num==2) |
24 | | 28 | Int32 | Number of Spew Points |
25 | | 32 | CarSpewStartPoint | Spew Start Points |
26 |
27 | ## Car Spew Start Point
28 |
29 | | Offset | Type | Explaination |
30 | | ------ | --------- | ---------------------- |
31 | | 0 | Int32 | Reserved |
32 | | 4 | Vector3 | Position |
33 | | 12 | TileIndex | Tile Index |
34 | | 24 | Float | Heading (Default -999) |
35 |
--------------------------------------------------------------------------------
/docs/old/CommTowerDatabase.md:
--------------------------------------------------------------------------------
1 | # Comm Tower Database (CommTowerDatabase.r8)
2 |
3 | Contains a list of Comm Towers
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----------- | -------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of CommTowers |
11 | | 8 | CommTower[] | CommTowers |
12 |
13 | ## CommTower
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | ---------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | TileIndex | TileXZ |
19 | | 12 | Vector3 | Position |
20 | | 24 | R8String | Tower ID/Name |
21 | | ... | Byte | Channel |
22 | | ... | R8String | Dial Code |
23 | | ... | R8String | Emergency Dial Code |
24 | | ... | Float | Range Meters |
25 | | ... | R8String | Dispatch Tone Cue Name |
26 |
--------------------------------------------------------------------------------
/docs/old/DefectDetectorList.md:
--------------------------------------------------------------------------------
1 | # Defect Detector List (DefectDetectorList.r8)
2 |
3 | Contains a list of defect detectors.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ---------------- | -------------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Defect Detectors |
11 | | 8 | DefectDetector[] | Defect Detectors |
12 |
13 | ## Defect Detector
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | ----------------------------- |
17 | | 0 | Int32 | Version (v) |
18 | | 4 | Int32 | Milepost |
19 | | 8 | Int32 | Milepost Decimal |
20 | | 16 | TileIndex | Tile Index |
21 | | 28 | Vector3 | Position |
22 | | ... | Byte | IsAEI (IF v=2 otherwise skip) |
23 | | 29 | Byte | SquawkOnDefectOnly |
24 | | 30 | Byte | DraggingEquipment |
25 | | 31 | Byte | SquawkTemperature |
26 | | 32 | Byte | SquawkTrainSpeed |
27 | | 33 | Byte | Hotbox |
28 | | 34 | Byte | HiWide (Legacy, not used) |
29 | | 35 | R8String | WaveBankName |
30 | | ... | R8String | SoundBankName |
31 | | ... | Int32 | Track Number |
32 |
--------------------------------------------------------------------------------
/docs/old/DispatcherBlockLightDatabase.md:
--------------------------------------------------------------------------------
1 | # Dispatcher Block Light Database (DispatcherBlockLightDatabase.r8)
2 |
3 | List of Dispatcher Lights (whatever those are? something with lights in the dispatcher screen)
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----------------- | --------------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Dispatcher Lights |
11 | | 8 | DispatcherLight[] | Dispatcher Lights |
12 |
--------------------------------------------------------------------------------
/docs/old/DispatcherSignalControllerDatabase.md:
--------------------------------------------------------------------------------
1 | # Dispatcher Signal Controller Database (DispatcherSignalControllerDatabase.r8)
2 |
3 | List of Dispatcher Signal Controllers (whatever those are? something to do with dispatcher screen)
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ---------------------------- | ----------------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Controllers |
11 | | 8 | DispatcherSignalController[] | Dispatcher Signal Controllers |
12 |
13 | ## DispatcherSignalController
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------------- | ------------------------------------------------- |
17 | | 0 | Int32 | Unknown n |
18 | | 4 | Vector2 | ScreenXY1 |
19 | | 12 | DispatcherLight | See [DispatcherLight](/Common.md#DispatcherLight) |
20 | | ... | Int32 | Number of Signals |
21 | | ... | Int32[] | Signal Head IDs |
22 | | ... | String | Name? If n == 2 |
23 |
24 | - 1: This overrides the ScreenXY in DispatcherLightBlock
25 |
--------------------------------------------------------------------------------
/docs/old/DispatcherSwitchIconDatabase.md:
--------------------------------------------------------------------------------
1 | # Dispatcher Switch Icon Database (DispatcherSwitchIconDatabase.r8)
2 |
3 | Contains a list of Dispatcher Switch Icons
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ------------------ | --------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Icons |
11 | | 8 | DispatcherButton[] | Icons |
12 |
13 | ## DispatcherButton
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | --------------------------- |
17 | | 0 | Int32 | Unknown n |
18 | | 4 | Rectangle | Button |
19 | | 16 | Vector2 | ScreenXY |
20 | | ... | Int32 | Route Prefix |
21 | | ... | Int32 | Index |
22 | | ... | Int32 | Number of SignalControllers |
23 | | ... | Int32[] | Signal Controller IDs |
24 | | ... | String | Name? If n == 2 |
25 |
--------------------------------------------------------------------------------
/docs/old/HornBellConfiguration.md:
--------------------------------------------------------------------------------
1 | # Horn Bell Configuration (HornBellConfiguration.r8)
2 |
3 | Mapping of horn and bell names to xml file configurations
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----- | ------------ |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Horn Count |
11 | | 8 | Horn | Horns |
12 | | 12 | Int32 | Bell Count |
13 | | 16 | Bell | Bells |
14 |
15 | ## Horn
16 |
17 | | Offset | Type | Explaination |
18 | | ------ | -------- | ----------------------------------------------- |
19 | | 0 | R8String | Key: Locomotive XML filename |
20 | | ... | R8String | Value (regular string, no custom bs): Horn name |
21 |
22 | ## Bell
23 |
24 | | Offset | Type | Explaination |
25 | | ------ | -------- | ----------------------------------------------- |
26 | | 0 | R8String | Key: Locomotive XML Filename |
27 | | ... | R8String | Value (regular string, no custom bs): Bell name |
28 |
--------------------------------------------------------------------------------
/docs/old/Hump.md:
--------------------------------------------------------------------------------
1 | # Hump (Hump.r8)
2 |
3 | Contains hump configurations for a region
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----- | --------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Humps |
11 | | 8 | Hump | Hump |
12 |
13 | ## Hump
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | ---------- | --------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | R8String | Hump Name |
19 | | ... | Int32 | Number of HumpConfigs |
20 | | ... | HumpConfig | Configs |
21 |
22 | ## HumpConfig
23 |
24 | | Offset | Type | Explaination |
25 | | ------ | --------- | ----------------------- |
26 | | 0 | Int32 | Reserved |
27 | | 4 | Boolean | HasName |
28 | | 5 | R8String | Config Name1 |
29 | | ... | Int32 | Number of Tracks |
30 | | ... | HumpTrack | Tracks |
31 |
32 | - 1: Only read if HasName is True
33 |
34 | ## HumpTrack
35 |
36 | | Offset | Type | Explaination |
37 | | ------ | ---------- | -------------- |
38 | | 0 | Int32 | Reserved |
39 | | 4 | R8String | Track Name |
40 | | ... | Int32 | Number of Tags |
41 | | ... | R8String[] | Tags |
42 |
--------------------------------------------------------------------------------
/docs/old/HumpControllerList.md:
--------------------------------------------------------------------------------
1 | # Hump Controller List (HumpControllerList.r8)
2 |
3 | Contains hump controllers
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------------- | --------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Controllers |
11 | | 8 | HumpController | Controllers |
12 |
13 | ## HumpController
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | ------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | R8String | Hump Name |
19 | | ... | TileIndex | TileXZ |
20 | | ... | Vector3 | Position |
21 | | ... | R8String | Unused |
22 | | ... | Int32 | Number of TrackPath |
23 | | ... | TrackPath | TrackPaths |
24 |
25 | ## TrackPath
26 |
27 | | Offset | Type | Explaination |
28 | | ------ | ---------------- | -------------------------- |
29 | | 0 | Int32 | Reserved |
30 | | 4 | String | Track Name |
31 | | ... | Int32 | Number of SwitchConnection |
32 | | ... | SwitchConnection | SwitchConnections |
33 |
34 | ## SwitchConnection
35 |
36 | | Offset | Type | Explaination |
37 | | ------ | ------- | ------------------- |
38 | | 0 | Int32 | Reserved |
39 | | 4 | Int32 | Track Section Index |
40 | | 8 | Boolean | Is Reversed |
41 |
--------------------------------------------------------------------------------
/docs/old/IndustryConfiguration.md:
--------------------------------------------------------------------------------
1 | # Industry Configuration (.ind)
2 |
3 | Stores information about industries
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------- | -------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Industry Count |
11 | | 8 | Industry | Industries |
12 |
13 | ## Industry
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | -------- | -------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | R8String | Industry Name |
19 | | ... | R8String | Local Freight Code |
20 | | ... | R8String | Industry Tag |
21 | | ... | Byte | Unknown Boolean |
22 | | ... | Int32 | Industry Track Count |
23 | | ... | IndTrack | Industry Tracks |
24 |
25 | ## Industry Track
26 |
27 | | Offset | Type | Explaination |
28 | | ------ | ----- | ------------ |
29 | | 0 | Int32 | Unknown Int |
30 | | 4 | Int32 | Prefix |
31 | | 8 | Int32 | Section |
32 | | 12 | Int32 | Node |
33 |
34 | ## Car
35 |
36 | | Offset | Type | Explaination |
37 | | ------ | ----- | --------------- |
38 | | 0 | Int32 | Reserved |
39 | | 4 | Byte | Car Type |
40 | | 8 | Byte | Unknown Boolean |
41 | | 12 | Int32 | Unknown Int |
42 | | 16 | Int32 | Unknown Int |
43 | | 20 | Int32 | Unknown Int |
44 |
--------------------------------------------------------------------------------
/docs/old/MilepostDatabase.md:
--------------------------------------------------------------------------------
1 | # Milepost Database (MilepostDatabase.r8)
2 |
3 | Contains a list of mileposts and their information
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------- | -------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Milepost Count |
11 | | 8 | Milepost | Mileposts |
12 |
13 | ## Milepost
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | --------- | ------------ |
17 | | 0 | Int32 | Reserved |
18 | | 4 | R8String | Mile Marker? |
19 | | ... | R8String | Name |
20 | | ... | TileIndex | Tile Index |
21 | | ... | Vector3 | Location |
22 |
--------------------------------------------------------------------------------
/docs/old/README.md:
--------------------------------------------------------------------------------
1 | Old style of file format specs that were hand written
2 |
--------------------------------------------------------------------------------
/docs/old/RoadDatabase.md:
--------------------------------------------------------------------------------
1 | # Road Database (RoadDatabase.r8)
2 |
3 | Contains road information.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ----------- | ------------------ |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Sections |
11 | | 8 | RoadSection | Sections |
12 |
13 | ## RoadSection
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | -------- | ------------------------- |
17 | | 0 | Int32 | Unknown Int |
18 | | 4 | Int32 | Number of Nodes |
19 | | 8 | RoadNode | Nodes |
20 | | ... | Int32 | Unknown Int |
21 | | ... | Float | Reserved |
22 | | ... | Byte | RoadExtrusionType |
23 | | ... | Int32 | Num Lanes Per Side |
24 | | ... | Int32 | Lane Center Offset Meters |
25 | | ... | Int32 | Lane Spacing Meters |
26 |
27 | ## RoadNode
28 |
29 | | Offset | Type | Explaination |
30 | | ------ | --------- | ----------------- |
31 | | 0 | Int32 | Reserved |
32 | | 4 | TileIndex | TileXZ |
33 | | 12 | Vector3 | PositionXYZ |
34 | | 24 | Vector3 | TangentXYZ |
35 | | 36 | Vector3 | Reserved |
36 | | 48 | Int32 | Index |
37 | | 52 | Float | Unknown |
38 | | 56 | Int32 | Curve Sign |
39 | | 60 | Float | Unknown |
40 | | 64 | Float | Arc Length Meters |
41 | | 68 | Int32 | Num of Segments |
42 | | 72 | Int32 | Unknown |
43 | | 76 | Float | Max Speed MPH |
44 |
45 | ## RoadExtrusionType
46 |
47 | | Key | Value |
48 | | --- | ------- |
49 | | 0 | Unknown |
50 | | 1 | Unknown |
51 | | 2 | Unknown |
52 | | 3 | Unknown |
53 | | 4 | Unknown |
54 | | 5 | Unknown |
55 | | 6 | Unknown |
56 | | 7 | Unknown |
57 | | 8 | Unknown |
58 | | 9 | Unknown |
59 | | 10 | Unknown |
60 | | 11 | Unknown |
61 | | 12 | Unknown |
62 | | 13 | Unknown |
63 |
--------------------------------------------------------------------------------
/docs/old/Signal.md:
--------------------------------------------------------------------------------
1 | # Signal (.sig)
2 |
3 | Contains information related to a signal
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ------------ | ------------------------------------------------------------- |
9 | | 0 | String | Model Name |
10 | | ... | Int32 | leastRestrictiveSignalState |
11 | | ... | Byte | Unknown Boolean (might be related to signal instruction stop) |
12 | | ... | Byte | isDwarf |
13 | | ... | Int32 | SignalEntry1 Count |
14 | | ... | SignalEntry1 | SignalEntry1s |
15 |
16 | ## SignalLight
17 |
18 | | Offset | Type | Explaination |
19 | | ------ | --------- | --------------------------- |
20 | | 0 | Vector3 | Light Offset |
21 | | 12 | Vector4 | Color\* |
22 | | 24 | Float | Light Glare Radius (meters) |
23 | | 28 | Float | Light Range |
24 | | 32 | Int32 | Glare Count |
25 | | 36 | Vector3[] | Glares |
26 |
27 | \* W is constant at 1f
28 |
--------------------------------------------------------------------------------
/docs/old/Stars4.md:
--------------------------------------------------------------------------------
1 | # Stars4 (stars4.r8)
2 |
3 | Stars4 file seems to contain file paths to other r8 database files, along with some random strings which are all identified by their array index.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------- | -------------------- |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Strings |
11 | | 8 | R8String | Run8 Encoded Strings |
12 |
--------------------------------------------------------------------------------
/docs/old/TKB.md:
--------------------------------------------------------------------------------
1 | # Shader File (.tkb)
2 |
3 | These files are from SharpDX, they are compiled shaders/effects. I am not going to write a dedicated tool for these as they're a pain in the ass (for me at least) and the compiler already has the ability to dump the bytecode.
4 |
5 | ## Dump Bytecode
6 |
7 | You will need to get `tkfxc.exe` from SharpDX, rather then having to compile it, you can just get it precompiled from Nuget: https://www.nuget.org/api/v2/package/SharpDX/2.6.3. This will download `sharpdx.2.6.3.nupkg` which is just a zip file, you can either change the file extension from `.nupkg` to `.zip` or just open it with 7zip (or any other archive program really). The binary can be found in at `sharpdx.2.6.3\Bin\DirectX11_2-net40\tkfxc.exe`.
8 |
9 | Now you can just run:
10 |
11 | - `tkfxc.exe > bytecode.txt`
12 |
--------------------------------------------------------------------------------
/docs/old/TrackDatabase.md:
--------------------------------------------------------------------------------
1 | # Track Database (TrackDatabase.r8)
2 |
3 | Contain a list of track locations as well as other track related information.
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | -------------- | ------------------ |
9 | | 0 | Int32 | Reserved |
10 | | 4 | Int32 | Number of Sections |
11 | | 8 | TrackSection[] | Sections |
12 |
13 | ## Track Section
14 |
15 | | Offset | Type | Explaination |
16 | | ------ | ----------- | ------------------------- |
17 | | 0 | Int32 | Reserved |
18 | | 4 | Int32 | Number of Nodes |
19 | | 8 | TrackNode[] | Nodes |
20 | | ... | Int32 | Index |
21 | | ... | Byte | Switch Lever Position |
22 | | ... | Int32 | Number of Section Indices |
23 | | ... | Int32[] | Next Section Indices |
24 | | ... | Byte | Track Type |
25 | | ... | Double | Retarder MPH |
26 | | ... | Byte | Is Occupied |
27 | | ... | Byte | Switch Stand Left Side |
28 | | ... | Int32 | Switch Stand Type |
29 | | ... | Byte | Is CTC Switch |
30 |
31 | ## Track Node
32 |
33 | | Offset | Type | Explaination |
34 | | ------ | --------- | ---------------------------- |
35 | | 0 | Int32 | Reserved |
36 | | 4 | TileIndex | Tile Index |
37 | | 12 | Vector3 | Position |
38 | | 24 | Vector3 | Tangent Degrees |
39 | | 32 | Vector3 | End Position |
40 | | 44 | Int32 | Index |
41 | | 48 | Byte | Is Switch Node |
42 | | 49 | Byte | Is Reverse Path |
43 | | 50 | Float | Curvature Degrees |
44 | | 54 | Int32 | Curve Sign |
45 | | 58 | Float | Radius Meters |
46 | | 62 | Float | Arc Length Meters |
47 | | 66 | Int32 | Num Segments |
48 | | 70 | Int32 | Section this Node belongs to |
49 | | 74 | Byte | Is Selected |
50 |
--------------------------------------------------------------------------------
/docs/old/XNG.md:
--------------------------------------------------------------------------------
1 | # XNG
2 |
3 | Crossing Gates
4 |
5 | ## Header
6 |
7 | | Offset | Type | Explaination |
8 | | ------ | ------ | ----------------------------- |
9 | | 0 | Byte | Gate Rotation Type |
10 | | ... | String | Gate Model Name |
11 | | ... | String | Stand Model Name |
12 | | ... | Float | Active Degrees |
13 | | ... | Float | Inactive Degrees |
14 | | ... | Float | Rotation Degrees Per Second\* |
15 |
16 | \* This gets multiplied by a random float between the range of `-4f` and `3f`
17 |
18 | ## GateRotationType
19 |
20 | | Key | Value |
21 | | --- | ----------- |
22 | | 0 | Vertical |
23 | | 1 | Horizontal |
24 | | 2 | XBuckNoBell |
25 |
26 | Some methods to look into in the future:
27 |
28 | - 0x06002B51
29 |
--------------------------------------------------------------------------------
/docs/service_area_database.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # ServiceAreaDatabase (ServiceAreaDatabase.r8)
4 |
5 | ## Root Structure
6 |
7 | | Type | ID | Description |
8 | | ---------- | ---- | ----------- |
9 | | Int32 | reserved | This field is unused |
10 | | Int32 | num_service_areas | |
11 | | service_area[] | service_areas | |
12 |
13 |
14 | ## Types
15 |
16 | ### service_area
17 |
18 | | Type | ID | Description |
19 | | ---------- | ---- | ----------- |
20 | | Int32 | num | |
21 | | path1 | path11 | |
22 | | path2 | path22 | |
23 |
24 | - 1: Only if num == 1
25 | - 2: Only if num == 2
26 |
27 | ### path1
28 |
29 | | Type | ID | Description |
30 | | ---------- | ---- | ----------- |
31 | | [TileXZ](common.md#tilexz) | tile_xz | |
32 | | [Vector3](common.md#vector3) | position | |
33 | | Float | float0 | |
34 | | Boolean | bool0 | |
35 | | Boolean | bool1 | |
36 | | Boolean | bool2 | |
37 | | Boolean | bool3 | |
38 |
39 |
40 | ### path2
41 |
42 | | Type | ID | Description |
43 | | ---------- | ---- | ----------- |
44 | | [TileXZ](common.md#tilexz) | tile_xz | |
45 | | [Vector3](common.md#vector3) | position | |
46 | | Float | float0 | |
47 | | class646 | class646 | |
48 |
49 |
50 | ### class646
51 |
52 | | Type | ID | Description |
53 | | ---------- | ---- | ----------- |
54 | | Int8 | enum50_0 | |
55 | | Int8 | enum60_0 | |
56 | | Double | double1 | |
57 | | Double | double2 | |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/stars4.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Stars4 (stars4.r8)
4 |
5 | Contains a list of strings, including file paths. Strings are referenced by their index.
6 |
7 | ## Root Structure
8 |
9 | | Type | ID | Description |
10 | | ---------- | ---- | ----------- |
11 | | Int32 | reserved | This field is unused |
12 | | Int32 | num_entries | |
13 | | [R8String](common.md#r8string)[] | entries | |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/docs/tilescenery.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Tile Scenery File
4 |
5 | ## Root Structure
6 |
7 | | Type | ID | Description |
8 | | ---------- | ---- | ----------- |
9 | | Int32 | num_assets | |
10 | | asset[] | assets | |
11 |
12 |
13 | ## Types
14 |
15 | ### asset
16 |
17 | | Type | ID | Description |
18 | | ---------- | ---- | ----------- |
19 | | Int32 | num_decals | |
20 | | decal[] | decals | |
21 | | Int8 | disregard_bounding_test | |
22 | | [C# String](common.md#cs_string) | model_name | |
23 | | [Vector3](common.md#vector3) | position | |
24 | | [Vector3](common.md#vector3) | rotation | |
25 | | [Vector3](common.md#vector3) | scale | |
26 | | [TileXZ](common.md#tilexz) | tile_xz | |
27 |
28 |
29 | ### decal
30 |
31 | | Type | ID | Description |
32 | | ---------- | ---- | ----------- |
33 | | Float | color_r | |
34 | | Float | color_g | |
35 | | Float | color_b | |
36 | | Int32 | num_digits | |
37 | | digit[] | digits | |
38 | | [Vector3](common.md#vector3) | offset | |
39 | | [Vector3](common.md#vector3) | rotation_deg | |
40 | | Float | size | |
41 | | [C# String](common.md#cs_string) | texture_name | |
42 |
43 |
44 | ### digit
45 |
46 | | Type | ID | Description |
47 | | ---------- | ---- | ----------- |
48 | | Int32 | digit | |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/docs/tr2.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # TR2 Terrain Tile
4 |
5 | ## Root Structure
6 |
7 | | Type | ID | Description |
8 | | ---------- | ---- | ----------- |
9 | | [C# String](common.md#cs_string) | texture_1 | |
10 | | [C# String](common.md#cs_string) | texture_2 | |
11 | | [C# String](common.md#cs_string) | texture_3 | |
12 | | [C# String](common.md#cs_string) | texture_4 | |
13 | | chunk_row[] | chunks | Tile X |
14 | | Float | lon_east | |
15 | | Float | lon_west | |
16 | | Float | lat_north | |
17 | | Float | lat_south | |
18 |
19 |
20 | ## Types
21 |
22 | ### chunk_row
23 |
24 | | Type | ID | Description |
25 | | ---------- | ---- | ----------- |
26 | | chunk[] | chunks | Tile Y |
27 |
28 |
29 | ### chunk
30 |
31 | | Type | ID | Description |
32 | | ---------- | ---- | ----------- |
33 | | UInt32 | chunk_size | Number of elevation points in this chunk |
34 | | elevation_col[] | elevations_row | Chunk X |
35 |
36 |
37 | ### elevation_col
38 |
39 | | Type | ID | Description |
40 | | ---------- | ---- | ----------- |
41 | | Float[] | elevation | Chunk Y |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/Environment.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/Folders.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/Installer.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Run8Tools Installer
4 | true
5 | true
6 |
7 |
8 |
9 | TextureToolFiles
10 | TextureTool
11 | true
12 |
13 |
14 |
15 |
16 | ColladaConverterFiles
17 | ColladaConverter
18 | true
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/Package.en-us.wxl:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/Package.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/CS/Run8/Installer/assets/License.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Segoe UI;}}
2 | {\*\generator Riched20 10.0.18362}\viewkind4\uc1
3 | \pard\nowidctlpar\sb120\sa120\b\f0\fs20 MIT License\par
4 | \b0 Copyright (c) Puyodead1. All rights reserved.\par
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\par
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\par
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE\par
8 | }
9 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/Class252.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class Class252
4 | {
5 | public Quaternion[] quaternion_0 { get; set; }
6 |
7 | public Vector3[] vector3_0 { get; set; }
8 |
9 | public Quaternion quaternion_1 { get; set; }
10 |
11 | public Vector3 vector3_1 { get; set; }
12 |
13 | internal void method_0(float float_0)
14 | {
15 | if (this.quaternion_0.Length < 2)
16 | {
17 | this.quaternion_1 = Quaternion.Identity;
18 | this.vector3_1 = Vector3.Zero;
19 | return;
20 | }
21 | int num = Util.Utils.Clamp((int)(float_0 * (float)this.quaternion_0.Length - 2f), 0, this.quaternion_0.Length - 2);
22 | int num2 = Util.Utils.Clamp(num + 1, 0, this.quaternion_0.Length - 1);
23 | Quaternion quaternion = this.quaternion_0[num];
24 | Quaternion quaternion2 = this.quaternion_0[num2];
25 | Vector3 vector = this.vector3_0[num];
26 | Vector3 vector2 = this.vector3_0[num2];
27 | float num3 = 1f / (this.quaternion_0.Length - 1);
28 | float num4 = Util.Utils.Lerp(0f, 1f, float_0 - num3 * (float)num / num3);
29 | if (quaternion != quaternion2)
30 | {
31 | this.quaternion_1 = Quaternion.Lerp(quaternion, quaternion2, num4);
32 | }
33 | else
34 | {
35 | this.quaternion_1 = quaternion;
36 | }
37 | this.vector3_1 = Vector3.Lerp(vector, vector2, num4);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/DecalLoader.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class DecalLoader
4 | {
5 | public List Digits { get; set; } = new List();
6 | public string TextureName { get; set; }
7 | public float Size { get; set; }
8 | public Vector3 OffsetXYZ { get; set; }
9 | public Vector3 RotationDegXYZ { get; set; }
10 | public Vector3 ColorRGB { get; set; }
11 | public bool IsGaugeNeedle { get; set; }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/DispatcherLight.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Util;
2 |
3 | namespace LibRun8.Common
4 | {
5 | public class DispatcherLight
6 | {
7 | public Rectangle ButtonRectangle { get; set; }
8 | public List Indices { get; set; } = new List();
9 | public Vector2 ScreenXY { get; set; }
10 | public string String0 { get; set; } = string.Empty;
11 |
12 | public static DispatcherLight Read(BinaryReader reader)
13 | {
14 | DispatcherLight dispatcherBlockLight = new DispatcherLight();
15 | int num = reader.ReadInt32();
16 | dispatcherBlockLight.ButtonRectangle = reader.ReadRectangle();
17 | dispatcherBlockLight.ScreenXY = reader.ReadVector2();
18 | int numOfIndices = reader.ReadInt32();
19 | for (int i = 0; i < numOfIndices; i++)
20 | {
21 | dispatcherBlockLight.Indices.Add(reader.ReadInt32());
22 | }
23 | if (num == 2)
24 | {
25 | dispatcherBlockLight.String0 = reader.ReadString();
26 | }
27 |
28 | return dispatcherBlockLight;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/Int4.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public struct Int4
4 | {
5 | //
6 | // Summary:
7 | // The X component of the vector.
8 | public int X { get; set; }
9 |
10 | //
11 | // Summary:
12 | // The Y component of the vector.
13 | public int Y { get; set; }
14 |
15 | //
16 | // Summary:
17 | // The Z component of the vector.
18 | public int Z { get; set; }
19 |
20 | //
21 | // Summary:
22 | // The W component of the vector.
23 | public int W { get; set; }
24 |
25 | //
26 | // Summary:
27 | // Initializes a new instance of the Int4 struct.
28 | //
29 | // Parameters:
30 | // value:
31 | // The value that will be assigned to all components.
32 | public Int4(int value)
33 | {
34 | X = value;
35 | Y = value;
36 | Z = value;
37 | W = value;
38 | }
39 |
40 | //
41 | // Summary:
42 | // Initializes a new instance of the Int4 struct.
43 | //
44 | // Parameters:
45 | // x:
46 | // Initial value for the X component of the vector.
47 | //
48 | // y:
49 | // Initial value for the Y component of the vector.
50 | //
51 | // z:
52 | // Initial value for the Z component of the vector.
53 | //
54 | // w:
55 | // Initial value for the W component of the vector.
56 | public Int4(int x, int y, int z, int w)
57 | {
58 | X = x;
59 | Y = y;
60 | Z = z;
61 | W = w;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/LightLoader.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class LightLoader
4 | {
5 | public bool billboardGlare { get; set; }
6 |
7 | public float LightRange { get; set; }
8 |
9 | public float lightWidth { get; set; }
10 |
11 | public float LightIntensity { get; set; }
12 |
13 | public float decayExponent { get; set; } = 1f;
14 |
15 | public Vector3 LightOffsetXYZ { get; set; }
16 |
17 | public bool isSpotLight { get; set; }
18 |
19 | public Vector4 Color { get; set; }
20 |
21 | public Vector3 LightDirectionDeg { get; set; }
22 |
23 | public bool flashing { get; set; }
24 |
25 | public float flashTimeRandomVariation { get; set; }
26 |
27 | public double flashTimerSeconds { get; set; }
28 |
29 | public bool hasDayNiteSensor { get; set; }
30 |
31 | public float dayNiteSensorAmbientLevel { get; set; }
32 |
33 | public Vector3[] GlareList { get; set; }
34 |
35 | public float LightGlareRadiusMeters { get; set; } = 0.35f;
36 |
37 | public bool isHepPowered { get; set; }
38 |
39 | public bool isMarkerLight { get; set; }
40 |
41 | public bool isNumberboardLight { get; set; }
42 |
43 | public bool IsLimitedYardLight { get; set; }
44 |
45 | public bool renderGlareOnly { get; set; }
46 |
47 | public bool isIncandescent { get; set; } = true;
48 |
49 | public float glowScalar { get; set; }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/ModelObjectDefinition.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class ModelObjectDefinition
4 | {
5 | public string texture2D_0 { get; set; }
6 |
7 | public string texture2D_1 { get; set; }
8 |
9 | public string texture2D_2 { get; set; }
10 |
11 | public int BaseVertexLocation { get; set; }
12 |
13 | public int StartIndexLocation { get; set; }
14 |
15 | public int IndexCountPerInstance { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/ProceduralVegetation.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class ProceduralVegetation
4 | {
5 | public TileIndex TileXZ { get; set; }
6 | public int PlantCount { get; set; }
7 | public List Plants { get; set; } = new List();
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/Rectangle.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Globalization;
3 |
4 | namespace LibRun8.Common
5 | {
6 | public class Rectangle
7 | {
8 | public int X { get; set; }
9 |
10 | public int Y { get; set; }
11 |
12 | public int Width { get; set; }
13 |
14 | public int Height { get; set; }
15 |
16 | public override string ToString()
17 | {
18 | return string.Format(CultureInfo.InvariantCulture, "X:{0} Y:{1} Width:{2} Height:{3}", new object[] { this.X, this.Y, this.Width, this.Height });
19 | }
20 |
21 | public Rectangle(int x, int y, int width, int height)
22 | {
23 | this.X = x;
24 | this.Y = y;
25 | this.Width = width;
26 | this.Height = height;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/SceneryAssetLoader.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class SceneryAssetLoader
4 | {
5 | public string ModelName { get; set; }
6 | public TileIndex TileXZ { get; set; }
7 | public Vector3 PositionXYZ { get; set; }
8 | public Vector3 RotationXYZ { get; set; }
9 | public Vector3 Scale { get; set; }
10 | public bool DisregardBoundingTest { get; set; }
11 | public bool Bool0 { get; set; }
12 | public List DecalLoadList { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/TileIndex.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public class TileIndex
4 | {
5 | public int X { get; set; }
6 | public int Z { get; set; }
7 |
8 | public TileIndex()
9 | {
10 | X = 0;
11 | Z = 0;
12 | }
13 |
14 | public TileIndex(int x, int y)
15 | {
16 | X = x;
17 | Z = y;
18 | }
19 |
20 | public static TileIndex Read(BinaryReader reader)
21 | {
22 | TileIndex tileXZ = new TileIndex();
23 |
24 | tileXZ.X = reader.ReadInt32();
25 | tileXZ.Z = reader.ReadInt32();
26 |
27 | return tileXZ;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/Vector2.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public struct Vector2
4 | {
5 | //
6 | // Summary:
7 | // The X component of the vector.
8 | public float X { get; set; }
9 |
10 | //
11 | // Summary:
12 | // The Y component of the vector.
13 | public float Y { get; set; }
14 |
15 | //
16 | // Summary:
17 | // Initializes a new instance of the Vector2 struct.
18 | //
19 | // Parameters:
20 | // value:
21 | // The value that will be assigned to all components.
22 | public Vector2(float value)
23 | {
24 | X = value;
25 | Y = value;
26 | }
27 |
28 | //
29 | // Summary:
30 | // Initializes a new instance of the Vector2 struct.
31 | //
32 | // Parameters:
33 | // x:
34 | // Initial value for the X component of the vector.
35 | //
36 | // y:
37 | // Initial value for the Y component of the vector.
38 | public Vector2(float x, float y)
39 | {
40 | X = x;
41 | Y = y;
42 | }
43 |
44 | public override string ToString()
45 | {
46 | return string.Format("X={0};Y={1}", X, Y);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/Vector4.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public struct Vector4
4 | {
5 | public float X { get; set; }
6 | public float Y { get; set; }
7 | public float Z { get; set; }
8 | public float W { get; set; }
9 |
10 | //
11 | // Summary:
12 | // Initializes a new instance of the Vector4 struct.
13 | //
14 | // Parameters:
15 | // value:
16 | // The value that will be assigned to all components.
17 | public Vector4(float value)
18 | {
19 | X = value;
20 | Y = value;
21 | Z = value;
22 | W = value;
23 | }
24 |
25 | //
26 | // Summary:
27 | // Initializes a new instance of the Vector4 struct.
28 | //
29 | // Parameters:
30 | // x:
31 | // Initial value for the X component of the vector.
32 | //
33 | // y:
34 | // Initial value for the Y component of the vector.
35 | //
36 | // z:
37 | // Initial value for the Z component of the vector.
38 | //
39 | // w:
40 | // Initial value for the W component of the vector.
41 |
42 | public Vector4(float x, float y, float z, float w)
43 | {
44 | X = x;
45 | Y = y;
46 | Z = z;
47 | W = w;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Common/VertexStruct.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Common
2 | {
3 | public struct VertexStruct
4 | {
5 | public Vector3 Position;
6 |
7 | public Vector3 Normal;
8 |
9 | public Vector2 TextureCoordinate;
10 |
11 | public Vector3 Tangent;
12 |
13 | public Vector3 Binormal;
14 |
15 | public override string ToString()
16 | {
17 | return string.Format("Position: {0}; Normal: {1}; TextureCoordinate: {2}", Position.ToString(), Normal.ToString(), TextureCoordinate.ToString());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/AISignalDatabase.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Low Accuracy
3 | */
4 |
5 | namespace LibRun8.Formats
6 | {
7 | public class AISignalDatabase : FileFormat
8 | {
9 | public List Signals { get; set; } = new List();
10 |
11 | public static AISignalDatabase Read(string path)
12 | {
13 | AISignalDatabase aiSignalDatabase = new AISignalDatabase();
14 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
15 | {
16 | using (BinaryReader reader = new BinaryReader(fileStream))
17 | {
18 | reader.ReadInt32(); // reserved
19 |
20 | var signalCount = reader.ReadInt32();
21 | for (int i = 0; i < signalCount; i++)
22 | {
23 | AISignal aiSignal = AISignal.Read(reader);
24 | aiSignalDatabase.Signals.Add(aiSignal);
25 | }
26 | }
27 | }
28 |
29 | return aiSignalDatabase;
30 | }
31 |
32 | public override void Write(string path)
33 | {
34 | throw new NotImplementedException();
35 | }
36 |
37 | public class AISignal
38 | {
39 | public List SignalIndices { get; set; } = new List(); // maps signal head signal index -> signal
40 | public bool Bool0 { get; set; }
41 | public int Int0 { get; set; }
42 | public int Int1 { get; set; }
43 | public Class336 Class336_0 { get; set; }
44 | public Class336 Class336_1 { get; set; }
45 |
46 | public static AISignal Read(BinaryReader reader)
47 | {
48 | AISignal aiSignal = new AISignal();
49 |
50 | reader.ReadInt32(); // reserved
51 | var count = reader.ReadInt32();
52 | for (int i = 0; i < count; i++)
53 | {
54 | aiSignal.SignalIndices.Add(reader.ReadInt32());
55 | }
56 |
57 | aiSignal.Bool0 = reader.ReadBoolean();
58 | aiSignal.Int0 = reader.ReadInt32();
59 | aiSignal.Int1 = reader.ReadInt32();
60 |
61 | if(reader.ReadBoolean())
62 | {
63 | aiSignal.Class336_0 = Class336.Read(reader);
64 | }
65 |
66 | if(reader.ReadBoolean())
67 | {
68 | aiSignal.Class336_1 = Class336.Read(reader);
69 | }
70 |
71 | return aiSignal;
72 | }
73 | }
74 |
75 | public class Class336
76 | {
77 | public int Int0 { get; set; }
78 | public int Int1 { get; set; }
79 | public static Class336 Read(BinaryReader reader)
80 | {
81 | Class336 @class = new Class336();
82 | @class.Int0 = reader.ReadInt32();
83 | @class.Int1 = reader.ReadInt32();
84 |
85 | return @class;
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/AITrackSpeedDatabase.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * Low Accuracy
3 | */
4 |
5 | namespace LibRun8.Formats
6 | {
7 | public class AITrackSpeedDatabase : FileFormat
8 | {
9 | public List TrackSpeeds { get; set; } = new List();
10 | public static AITrackSpeedDatabase Read(string path)
11 | {
12 | AITrackSpeedDatabase aiTrackSpeedDatabase = new AITrackSpeedDatabase();
13 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
14 | {
15 | using (BinaryReader reader = new BinaryReader(fileStream))
16 | {
17 | reader.ReadInt32(); // reserved
18 | var count = reader.ReadInt32();
19 | for (int i = 0; i < count; i++)
20 | {
21 | aiTrackSpeedDatabase.TrackSpeeds.Add(TrackSpeed.Read(reader));
22 | }
23 | }
24 | }
25 |
26 | return aiTrackSpeedDatabase;
27 | }
28 |
29 | public override void Write(string path)
30 | {
31 | throw new NotImplementedException();
32 | }
33 |
34 | public class TrackSpeedEntry
35 | {
36 | public int Int0 { get; set; }
37 | public int Int1 { get; set; } = 15;
38 | public int Int2 { get; set; } = 15;
39 | public static TrackSpeedEntry Read(BinaryReader reader)
40 | {
41 | TrackSpeedEntry class317 = new TrackSpeedEntry();
42 |
43 | reader.ReadInt32(); // reserved
44 | class317.Int0 = reader.ReadInt32();
45 | class317.Int1 = reader.ReadInt32();
46 | class317.Int2 = reader.ReadInt32();
47 |
48 | return class317;
49 | }
50 | }
51 |
52 | public class TrackSpeed
53 | {
54 | public List Speeds { get; set; } = new List();
55 | public int Int0 { get; set; }
56 | public static TrackSpeed Read(BinaryReader reader)
57 | {
58 | TrackSpeed trackSpeed = new TrackSpeed();
59 |
60 | reader.ReadInt32(); // reserved
61 | trackSpeed.Int0 = reader.ReadInt32();
62 | var count = reader.ReadInt32();
63 | for (int i = 0; i < count; i++)
64 | {
65 | trackSpeed.Speeds.Add(TrackSpeedEntry.Read(reader));
66 | }
67 |
68 | return trackSpeed;
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/BlockDetectorDatabase.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace LibRun8.Formats
5 | {
6 | public class BlockDetectorDatabase : FileFormat
7 | {
8 | public List Detectors { get; set; } = new List();
9 | public static BlockDetectorDatabase Read(string path)
10 | {
11 | BlockDetectorDatabase blockDetectorDatabase = new BlockDetectorDatabase();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | reader.ReadInt32(); // reserved
17 | var numOfDetectors = reader.ReadInt32();
18 | for (int i = 0; i < numOfDetectors; i++)
19 | {
20 | BlockDetector blockDetector = BlockDetector.Read(reader);
21 | blockDetectorDatabase.Detectors.Add(blockDetector);
22 | }
23 | }
24 | }
25 |
26 | return blockDetectorDatabase;
27 | }
28 |
29 | public override void Write(string path)
30 | {
31 | throw new NotImplementedException();
32 | }
33 |
34 | public class BlockDetector
35 | {
36 | public int Index { get; set; }
37 | public List Tracks { get; set; } = new List();
38 | public TileIndex TileXZ { get; set; }
39 | public Vector3 PositionXYZ { get; set; }
40 |
41 | public static BlockDetector Read(BinaryReader reader)
42 | {
43 | BlockDetector blockDetector = new BlockDetector();
44 |
45 | reader.ReadInt32(); // reserved
46 | blockDetector.Index = reader.ReadInt32();
47 | var numOfTracks = reader.ReadInt32();
48 | for (int i = 0; i < numOfTracks; i++)
49 | {
50 | blockDetector.Tracks.Add(reader.ReadInt32());
51 | }
52 | blockDetector.TileXZ = reader.ReadTileIndex();
53 | blockDetector.PositionXYZ = reader.ReadVector3();
54 |
55 | return blockDetector;
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/CarSpewerDatabase.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace LibRun8.Formats
5 | {
6 | public class CarSpewerDatabase : FileFormat
7 | {
8 | public List Spewers { get; set; } = new List();
9 | public static CarSpewerDatabase Read(string path)
10 | {
11 | CarSpewerDatabase carSpewerDatabase = new CarSpewerDatabase();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | reader.ReadInt32(); // reserved
17 | var numOfSpewers = reader.ReadInt32();
18 | for (int i = 0; i < numOfSpewers; i++)
19 | {
20 | carSpewerDatabase.Spewers.Add(CarSpewer.Read(reader));
21 | }
22 | }
23 | }
24 |
25 | return carSpewerDatabase;
26 | }
27 |
28 | public override void Write(string path)
29 | {
30 | throw new NotImplementedException();
31 | }
32 |
33 | public class CarSpewer
34 | {
35 | public int Int0 { get; set; } // Doesn't appear to ever be used
36 | public int RoadNodeIndex { get; set; }
37 | public int MaxNumCars { get; set; }
38 | public double MinTimeBetwixtSpew { get; set; }
39 | public double MaxTimeBetwixtSpew { get; set; }
40 | public float MaxSpeed { get; set; }
41 | public List CarSpewStartPoints { get; set; } = new List();
42 |
43 | public static CarSpewer Read(BinaryReader reader)
44 | {
45 | CarSpewer carSpewer = new CarSpewer();
46 |
47 | var num = reader.ReadInt32();
48 | carSpewer.Int0 = reader.ReadInt32();
49 | carSpewer.RoadNodeIndex = reader.ReadInt32();
50 | carSpewer.MaxNumCars = reader.ReadInt32();
51 | carSpewer.MinTimeBetwixtSpew = reader.ReadDouble();
52 | carSpewer.MaxTimeBetwixtSpew = reader.ReadDouble();
53 | if (num == 2)
54 | {
55 | carSpewer.MaxSpeed = reader.ReadSingle();
56 | }
57 | var numOfSpewStartPoints = reader.ReadInt32();
58 | for (int i = 0; i < numOfSpewStartPoints; i++)
59 | {
60 | carSpewer.CarSpewStartPoints.Add(CarSpewStartPoint.Read(reader));
61 | }
62 |
63 | return carSpewer;
64 | }
65 | }
66 |
67 | public class CarSpewStartPoint
68 | {
69 | public Vector3 PosXYZ { get; set; }
70 | public TileIndex TileXZ { get; set; }
71 | public float Heading { get; set; } = -999f;
72 |
73 | public static CarSpewStartPoint Read(BinaryReader reader)
74 | {
75 | CarSpewStartPoint carSpewStartPoint = new CarSpewStartPoint();
76 |
77 | reader.ReadInt32();
78 | carSpewStartPoint.PosXYZ = reader.ReadVector3();
79 | carSpewStartPoint.TileXZ = reader.ReadTileIndex();
80 | carSpewStartPoint.Heading = reader.ReadSingle();
81 |
82 | return carSpewStartPoint;
83 | }
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/DefectDetector.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace LibRun8.Formats
5 | {
6 | public class DefectDetector
7 | {
8 | public int Version { get; set; } = 2;
9 | public int Milepost { get; set; }
10 | public int MilepostDecimal { get; set; }
11 | public TileIndex TileXZ { get; set; }
12 | public Vector3 PositionXYZ { get; set; }
13 | public bool? IsAEI { get; set; }
14 | public bool SquawkOnDefectOnly { get; set; }
15 | public bool DraggingEquipment { get; set; }
16 | public bool SquawkTemperature { get; set; }
17 | public bool SquawkTrainSpeed { get; set; }
18 | public bool Hotbox { get; set; }
19 | public bool HiWide { get; set; } // legacy, not used
20 | public string WaveBankName { get; set; }
21 | public string SoundBankName { get; set; }
22 | public int TrackNumber { get; set; }
23 |
24 | public static DefectDetector Read(BinaryReader reader)
25 | {
26 | DefectDetector defectDetector = new DefectDetector();
27 | defectDetector.Version = reader.ReadInt32();
28 | if (defectDetector.Version == 1)
29 | {
30 | defectDetector.Milepost = reader.ReadInt32();
31 | defectDetector.MilepostDecimal = reader.ReadInt32();
32 | defectDetector.TileXZ = reader.ReadTileIndex();
33 | defectDetector.PositionXYZ = reader.ReadVector3();
34 | defectDetector.SquawkOnDefectOnly = reader.ReadBoolean();
35 | defectDetector.DraggingEquipment = reader.ReadBoolean();
36 | defectDetector.SquawkTemperature = reader.ReadBoolean();
37 | defectDetector.SquawkTrainSpeed = reader.ReadBoolean();
38 | defectDetector.Hotbox = reader.ReadBoolean();
39 | defectDetector.HiWide = reader.ReadBoolean();
40 | defectDetector.WaveBankName = reader.ReadR8String();
41 | defectDetector.SoundBankName = reader.ReadR8String();
42 | defectDetector.TrackNumber = reader.ReadInt32();
43 | }
44 |
45 | if (defectDetector.Version == 2)
46 | {
47 | defectDetector.Milepost = reader.ReadInt32();
48 | defectDetector.MilepostDecimal = reader.ReadInt32();
49 | defectDetector.TileXZ = reader.ReadTileIndex();
50 | defectDetector.PositionXYZ = reader.ReadVector3();
51 | defectDetector.IsAEI = reader.ReadBoolean();
52 | defectDetector.SquawkOnDefectOnly = reader.ReadBoolean();
53 | defectDetector.DraggingEquipment = reader.ReadBoolean();
54 | defectDetector.SquawkTemperature = reader.ReadBoolean();
55 | defectDetector.SquawkTrainSpeed = reader.ReadBoolean();
56 | defectDetector.Hotbox = reader.ReadBoolean();
57 | defectDetector.HiWide = reader.ReadBoolean();
58 | defectDetector.WaveBankName = reader.ReadR8String();
59 | defectDetector.SoundBankName = reader.ReadR8String();
60 | defectDetector.TrackNumber = reader.ReadInt32();
61 | }
62 |
63 | return defectDetector;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/DefectDetectorList.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Util;
2 |
3 | namespace LibRun8.Formats
4 | {
5 | public class DefectDetectorList : FileFormat
6 | {
7 | public List DefectDetectors { get; set; } = new List();
8 | public static DefectDetectorList Read(string path)
9 | {
10 | DefectDetectorList defectDetectorList = new DefectDetectorList();
11 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
12 | {
13 | using (BinaryReader reader = new BinaryReader(fileStream))
14 | {
15 | reader.ReadInt32(); // reserved
16 | int numOfDetectors = reader.ReadInt32();
17 | for (int i = 0; i < numOfDetectors; i++)
18 | {
19 | defectDetectorList.DefectDetectors.Add(DefectDetector.Read(reader));
20 | }
21 | }
22 | }
23 |
24 | return defectDetectorList;
25 | }
26 |
27 | public override void Write(string path)
28 | {
29 | using (FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate))
30 | using (BinaryWriter writer = new BinaryWriter(fileStream))
31 | {
32 |
33 | writer.Write(1); // reserved
34 | writer.Write(DefectDetectors.Count);
35 | foreach (DefectDetector defectDetector in DefectDetectors)
36 | {
37 | writer.Write(defectDetector.Version);
38 | writer.Write(defectDetector.Milepost);
39 | writer.Write(defectDetector.MilepostDecimal);
40 | writer.WriteTileIndex(defectDetector.TileXZ);
41 | writer.WriteVector3(defectDetector.PositionXYZ);
42 | if (defectDetector.Version == 2)
43 | {
44 | if(!defectDetector.IsAEI.HasValue)
45 | {
46 | throw new Exception("IsAEI must have a value when version is 2!");
47 | }
48 | writer.Write(defectDetector.IsAEI.Value);
49 | }
50 | writer.Write(defectDetector.SquawkOnDefectOnly);
51 | writer.Write(defectDetector.DraggingEquipment);
52 | writer.Write(defectDetector.SquawkTemperature);
53 | writer.Write(defectDetector.SquawkTrainSpeed);
54 | writer.Write(defectDetector.Hotbox);
55 | writer.Write(defectDetector.HiWide);
56 | writer.WriteR8String(defectDetector.WaveBankName);
57 | writer.WriteR8String(defectDetector.SoundBankName);
58 | writer.Write(defectDetector.TrackNumber);
59 | }
60 | }
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/DispatcherLightBlockDatabase.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace LibRun8.Formats
4 | {
5 | public class DispatcherLightBlockDatabase : FileFormat
6 | {
7 | public List DispatchLights { get; set; } = new List();
8 | public static DispatcherLightBlockDatabase Read(string path)
9 | {
10 | DispatcherLightBlockDatabase dispatcherLightBlockDatabase = new DispatcherLightBlockDatabase();
11 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
12 | {
13 | using (BinaryReader reader = new BinaryReader(fileStream))
14 | {
15 | reader.ReadInt32(); // reserved
16 | int numOfBlocks = reader.ReadInt32();
17 | for (int i = 0; i < numOfBlocks; i++)
18 | {
19 | dispatcherLightBlockDatabase.DispatchLights.Add(DispatcherLight.Read(reader));
20 | }
21 | }
22 | }
23 |
24 | return dispatcherLightBlockDatabase;
25 | }
26 |
27 | public override void Write(string path)
28 | {
29 | throw new NotImplementedException();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/DispatcherSignalControllerDatabase.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace LibRun8.Formats
5 | {
6 | public class DispatcherSignalControllerDatabase : FileFormat
7 | {
8 | public List Controllers { get; private set; } = new List();
9 | public static DispatcherSignalControllerDatabase Read(string path)
10 | {
11 | DispatcherSignalControllerDatabase item = new DispatcherSignalControllerDatabase();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | reader.ReadInt32(); // reserved
17 | int numOfControllers = reader.ReadInt32();
18 | for (int i = 0; i < numOfControllers; i++)
19 | {
20 | item.Controllers.Add(DispatcherSignalController.Read(reader));
21 | }
22 | }
23 | }
24 |
25 | return item;
26 | }
27 |
28 | public override void Write(string path)
29 | {
30 | throw new NotImplementedException();
31 | }
32 |
33 | public class DispatcherSignalController
34 | {
35 | public DispatcherLight Button { get; set; }
36 | public List Signals { get; set; } = new List();
37 | public string String0 { get; set; } = string.Empty;
38 | public static DispatcherSignalController Read(BinaryReader reader)
39 | {
40 | DispatcherSignalController controller = new DispatcherSignalController();
41 |
42 | int num = reader.ReadInt32();
43 | Vector2 screenXY = reader.ReadVector2();
44 | controller.Button = DispatcherLight.Read(reader);
45 | controller.Button.ScreenXY = screenXY;
46 |
47 | int numOfSignals = reader.ReadInt32();
48 | for (int i = 0; i < numOfSignals; i++)
49 | {
50 | controller.Signals.Add(reader.ReadInt32());
51 | }
52 |
53 | if(num == 2)
54 | {
55 | controller.String0 = reader.ReadString();
56 | }
57 |
58 | return controller;
59 | }
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/DispatcherSwitchIconDatabase.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace LibRun8.Formats
5 | {
6 | public class DispatcherSwitchIconDatabase : FileFormat
7 | {
8 | public List Buttons { get; set; } = new List();
9 | public static DispatcherSwitchIconDatabase Read(string path)
10 | {
11 | DispatcherSwitchIconDatabase item = new DispatcherSwitchIconDatabase();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | reader.ReadInt32(); // reserved
17 | int numOfIcons = reader.ReadInt32();
18 | for (int i = 0; i < numOfIcons; i++)
19 | {
20 | item.Buttons.Add(DispatcherButton.Read(reader));
21 | }
22 | }
23 | }
24 |
25 | return item;
26 | }
27 |
28 | public override void Write(string path)
29 | {
30 | throw new NotImplementedException();
31 | }
32 |
33 | public class DispatcherButton
34 | {
35 | public Rectangle Button { get; set; }
36 | public Vector2 ScreenXY { get; set; }
37 | public int RoutePrefix { get; set; }
38 | public int Index { get; set; }
39 | public List SwitchControllers { get; set; } = new List();
40 | public string String0 { get; set; } = string.Empty;
41 |
42 | public static DispatcherButton Read(BinaryReader reader)
43 | {
44 | DispatcherButton dispatcherButton = new DispatcherButton();
45 |
46 | int num = reader.ReadInt32();
47 | dispatcherButton.Button = reader.ReadRectangle();
48 | dispatcherButton.ScreenXY = reader.ReadVector2();
49 | dispatcherButton.RoutePrefix = reader.ReadInt32();
50 | dispatcherButton.Index = reader.ReadInt32();
51 | int numOfSwitchControllers = reader.ReadInt32();
52 |
53 | for (int i = 0; i < numOfSwitchControllers; i++)
54 | {
55 | dispatcherButton.SwitchControllers.Add(reader.ReadInt32());
56 | }
57 |
58 | if (num == 2)
59 | {
60 | dispatcherButton.String0 = reader.ReadString();
61 | }
62 |
63 | return dispatcherButton;
64 | }
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/FileFormat.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Formats
2 | {
3 | public abstract class FileFormat
4 | {
5 | public abstract void Write(string path);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Signal.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace LibRun8.Formats
4 | {
5 | public class Signal : FileFormat
6 | {
7 | public string ModelName { get; set; }
8 | public int LeastRestrictiveSignalState { get; set; }
9 | public bool B0 { get; set; }
10 | public bool IsDwarf { get; set; }
11 | public SignalLight[] SignalLights { get; set; }
12 |
13 | public static Signal Read(string path)
14 | {
15 | Signal signal = new Signal();
16 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
17 | {
18 | using (BinaryReader reader = new BinaryReader(fileStream))
19 | {
20 | signal.ModelName = reader.ReadString();
21 | signal.LeastRestrictiveSignalState = reader.ReadInt32();
22 | signal.B0 = reader.ReadBoolean();
23 | signal.IsDwarf = reader.ReadBoolean();
24 |
25 | int signalCount = reader.ReadInt32();
26 | signal.SignalLights = new SignalLight[signalCount];
27 |
28 | for(int i = 0; i < signalCount; i++)
29 | {
30 | SignalLight light = new SignalLight();
31 | light.LightOffset = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
32 | light.Color = new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), 1f);
33 | light.LightGlareRadiusMeters = reader.ReadSingle();
34 | light.LightRange = reader.ReadSingle();
35 |
36 | int VectorCount = reader.ReadInt32();
37 | light.GlareList = new Vector3[VectorCount];
38 |
39 | for(int j = 0; j < VectorCount; j++)
40 | {
41 | light.GlareList[j] = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
42 | }
43 |
44 | signal.SignalLights[i] = light;
45 | }
46 | }
47 | }
48 |
49 | return signal;
50 | }
51 |
52 | public override void Write(string path)
53 | {
54 | throw new NotImplementedException();
55 | }
56 |
57 | public class SignalLight
58 | {
59 | public Vector3 LightOffset { get; set; }
60 | public Vector3 lightDirectionDeg { get; set; }
61 | public Vector3[] GlareList { get; set; }
62 | public Vector4 Color { get; set; }
63 | public float LightGlareRadiusMeters { get; set; } = 0.35f;
64 | public float LightRange { get; set; }
65 | public float LightIntensity { get; set; }
66 | public bool IsLimitedYardLight { get; set; }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Stars4.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Util;
2 |
3 | namespace LibRun8.Formats
4 | {
5 | public class Stars4 : FileFormat
6 | {
7 | public string[] Entries { get; set; }
8 |
9 | public static Stars4 Read(string path)
10 | {
11 | Stars4 stars4 = new Stars4();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | reader.ReadInt32();
17 | int entryCount = reader.ReadInt32();
18 | stars4.Entries = new string[entryCount];
19 |
20 | for(int i = 0; i < stars4.Entries.Length; i++)
21 | {
22 | stars4.Entries[i] = reader.ReadR8String();
23 | }
24 | }
25 | }
26 |
27 | return stars4;
28 | }
29 |
30 | public override void Write(string path)
31 | {
32 | throw new NotImplementedException();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Terrain/Chunk.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | namespace LibRun8.Formats.Terrain
3 | {
4 | public class Chunk
5 | {
6 | public static readonly int CHUNK_SIZE = 25;
7 |
8 | public float[,] HeightMap;
9 | public float[][] JaggedHeightMap { get { return Util.Utils.ConvertToJaggedArray(HeightMap); } }
10 | public short Hixels { get; set; }
11 | public int CX { get; set; }
12 | public int CZ { get; set; }
13 | public VertexStruct[] Vertices { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Terrain/ETileType.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Formats.Terrain
2 | {
3 | public enum ETileType
4 | {
5 | None,
6 | Ter,
7 | Tr2,
8 | Tr3,
9 | Tr4
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Terrain/TerrainTile.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace LibRun8.Formats.Terrain
4 | {
5 | public class TerrainTile
6 | {
7 | public string Texture0Name { get; set; }
8 | public string Texture1Name { get; set; }
9 | public string Texture2Name { get; set; }
10 | public string Texture3Name { get; set; }
11 | public int DetailLevel { get; set; }
12 | public Chunk[,] ChunkData { get; set; }
13 | public float LonWest { get; set; }
14 | public float LonEast { get; set; }
15 | public float LatNorth { get; set; }
16 | public float LatSouth { get; set; }
17 | public string ProcVeg { get; set; }
18 | public VertexStruct[] AllVerticesTemp { get; set; }
19 | public int[] IndexBuffer { get; set; }
20 | public TileIndex TileXZ { get; set; }
21 | public List LoadList { get; set; } = new List();
22 | public ProceduralVegetation Plants { get; set; }
23 | public byte[] WeightMap { get; set; }
24 | public Vector2 CenterXZ { get; set; }
25 | public float CenterY { get; set; }
26 |
27 | public void CopyToVertexBuffers()
28 | {
29 | for (int i = 0; i < this.AllVerticesTemp.Length; i++)
30 | {
31 | Vector2 textureCoordinate = default;
32 | textureCoordinate.X = this.AllVerticesTemp[i].Position.X / 844.3211f;
33 | textureCoordinate.Y = -this.AllVerticesTemp[i].Position.Z / 1026.0822f;
34 | this.AllVerticesTemp[i].TextureCoordinate = textureCoordinate;
35 | }
36 |
37 | //this.indexBuffer = null;
38 | //this.allVerticesTemp = null;
39 | }
40 |
41 | public void WriteOBJ(string path)
42 | {
43 |
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Terrain/TerrainTileLoadData.cs:
--------------------------------------------------------------------------------
1 | namespace LibRun8.Formats.Terrain
2 | {
3 | public class TerrainTileLoadData
4 | {
5 | public string FilePath { get; set; }
6 | public string FileNameOnly { get; set; }
7 | public ETileType Type { get; set; }
8 | public TerrainTile Tile { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/Terrain/Tr2Loader.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Util;
2 |
3 | namespace LibRun8.Formats.Terrain
4 | {
5 | public class Tr2Loader
6 | {
7 | public static void LoadTile(TerrainTileLoadData terrainTileLoadData)
8 | {
9 | LoadTile(terrainTileLoadData, false);
10 | }
11 |
12 | public static void LoadTile(TerrainTileLoadData terrainTileLoadData, bool bool0)
13 | {
14 | using (FileStream fileStream = new FileStream(terrainTileLoadData.FilePath, FileMode.Open, FileAccess.Read))
15 | {
16 | using (BinaryReader binaryReader = new BinaryReader(fileStream))
17 | {
18 | TileUtil.LoadTextures(binaryReader, terrainTileLoadData, bool0);
19 | LoadChunks(binaryReader, terrainTileLoadData);
20 | }
21 | }
22 | }
23 |
24 | public static void LoadChunks(BinaryReader reader, TerrainTileLoadData terrainTileLoadData)
25 | {
26 | terrainTileLoadData.Tile.DetailLevel = 99;
27 | terrainTileLoadData.Tile.ChunkData = new Chunk[25, 25];
28 | //int num = 0;
29 | for (byte x = 0; x < 25; x++)
30 | {
31 | for (byte z = 0; z < 25; z++)
32 | {
33 | Chunk chunk = new Chunk();
34 | chunk.Hixels = (short)reader.ReadInt32();
35 | chunk.HeightMap = new float[chunk.Hixels, chunk.Hixels];
36 | chunk.CX = x;
37 | chunk.CZ = z;
38 |
39 | for (int i = 0; i < chunk.Hixels; i++)
40 | {
41 | for (int j = 0; j < chunk.Hixels; j++)
42 | {
43 | float elevation = reader.ReadSingle();
44 | chunk.HeightMap[i, j] = elevation;
45 | //if(elevation <= heightOffset + 0.2f)
46 | //{
47 | // num++;
48 | //}
49 | }
50 | }
51 |
52 | terrainTileLoadData.Tile.ChunkData[x, z] = chunk;
53 | }
54 | }
55 |
56 | //unknown0 = region == "SouthernCA" && num > 100;
57 |
58 | try
59 | {
60 | terrainTileLoadData.Tile.LonEast = reader.ReadSingle();
61 | terrainTileLoadData.Tile.LonWest = reader.ReadSingle();
62 | terrainTileLoadData.Tile.LatNorth = reader.ReadSingle();
63 | terrainTileLoadData.Tile.LatSouth = reader.ReadSingle();
64 | terrainTileLoadData.Tile.ProcVeg = reader.ReadString();
65 | }
66 | catch { }
67 |
68 | // this calculates vertex and index buffer
69 | TileUtil.smethod_13(terrainTileLoadData.Tile);
70 | }
71 |
72 | public void Write(string path)
73 | {
74 | throw new NotImplementedException();
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Formats/TileScenery.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace LibRun8.Formats
4 | {
5 | public class TileScenery : FileFormat
6 | {
7 | public List LoadList = new List();
8 |
9 | public static TileScenery Read(string path)
10 | {
11 | TileScenery item = new TileScenery();
12 | using (FileStream fileStream = new FileStream(path, FileMode.Open))
13 | {
14 | using (BinaryReader reader = new BinaryReader(fileStream))
15 | {
16 | // this is a copy of the LoadSceneryItems method from Tr4Loader.cs
17 | int count = reader.ReadInt32();
18 |
19 | for (int i = 0; i < count; i++)
20 | {
21 | SceneryAssetLoader sceneryAssetLoader = new SceneryAssetLoader
22 | {
23 | DecalLoadList = new List()
24 | };
25 |
26 | int decalCount = reader.ReadInt32();
27 |
28 | for (int j = 0; j < decalCount; j++)
29 | {
30 | DecalLoader decalLoader = new DecalLoader
31 | {
32 | ColorRGB = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()),
33 | };
34 |
35 | int digitCount = reader.ReadInt32();
36 | for (int k = 0; k < digitCount; k++)
37 | {
38 | decalLoader.Digits.Add(reader.ReadInt32());
39 | }
40 |
41 | decalLoader.OffsetXYZ = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
42 | decalLoader.RotationDegXYZ = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
43 | decalLoader.Size = reader.ReadSingle();
44 | decalLoader.TextureName = reader.ReadString();
45 | sceneryAssetLoader.DecalLoadList.Add(decalLoader);
46 | }
47 |
48 | sceneryAssetLoader.DisregardBoundingTest = reader.ReadBoolean();
49 | sceneryAssetLoader.ModelName = reader.ReadString();
50 | sceneryAssetLoader.PositionXYZ = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
51 | sceneryAssetLoader.RotationXYZ = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
52 | sceneryAssetLoader.Scale = new Vector3(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
53 | sceneryAssetLoader.TileXZ = new TileIndex(reader.ReadInt32(), reader.ReadInt32());
54 | item.LoadList.Add(sceneryAssetLoader);
55 | }
56 | }
57 | }
58 |
59 | return item;
60 | }
61 |
62 | public override void Write(string path)
63 | {
64 | throw new NotImplementedException();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/LibRun8.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 | enable
7 | true
8 | AnyCPU;x64
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Utils/BinaryWriterExtensions.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace LibRun8.Util
4 | {
5 | ///
6 | /// Provides some conspicuously absent string and Type functionality to
7 | ///
8 | ///
9 | static class BinaryWriterExtensions
10 | {
11 |
12 | public static void WriteVector3(this BinaryWriter writer, Vector3 vector)
13 | {
14 | writer.Write(vector.X);
15 | writer.Write(vector.Y);
16 | writer.Write(vector.Z);
17 | }
18 |
19 | public static void WriteTileIndex(this BinaryWriter writer, TileIndex TileXZ)
20 | {
21 | writer.Write(TileXZ.X);
22 | writer.Write(TileXZ.Z);
23 | }
24 |
25 | public static void WriteR8String(this BinaryWriter writer, string val)
26 | {
27 | if (val == null)
28 | {
29 | val = string.Empty;
30 | }
31 | byte[] array = R8String.EncodeBytes(val);
32 | writer.Write(array.Length);
33 | writer.Write(array);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/CS/Run8/LibRun8/Utils/R8String.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace LibRun8.Util
4 | {
5 | public class R8String
6 | {
7 | public static string DecodeBytes(byte[] bytes)
8 | {
9 | byte[] array = new byte[bytes.Length / 2];
10 | int num = 0;
11 | for (int i = 0; i < array.Length; i++)
12 | {
13 | byte[] array2 = array;
14 | int num2 = i;
15 | array2[num2] |= (byte)(bytes[num++] << 4);
16 | byte[] array3 = array;
17 | int num3 = i;
18 | array3[num3] |= (byte)(bytes[num++] >> 4);
19 | }
20 | return Encoding.UTF8.GetString(array);
21 | }
22 |
23 | public static byte[] EncodeBytes(string val)
24 | {
25 | byte[] bytes = Encoding.UTF8.GetBytes(val);
26 | byte[] array = new byte[bytes.Length * 2];
27 | int num = 0;
28 | for (int i = 0; i < bytes.Length; i++)
29 | {
30 | array[num++] = (byte)(bytes[i] >> 4);
31 | array[num++] = (byte)(bytes[i] << 4);
32 | }
33 | return array;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/ClassInfo.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class ClassInfo
4 | {
5 | public string ClassName { get; set; }
6 | public List Methods { get; set; }
7 | public List Fields { get; set; }
8 | public List Properties { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/ClassPair.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class ClassPair
4 | {
5 | public ClassInfo OldClass { get; set; }
6 | public ClassInfo NewClass { get; set; }
7 | public bool IsSameClass { get; set; } // Label: true if they are the same class, false otherwise
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/Extractor.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class Extractor
4 | {
5 | public static Dictionary GetClassesFromAssembly(string assemblyPath)
6 | {
7 | var classes = new Dictionary();
8 | var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyPath);
9 |
10 | foreach (var module in assembly.Modules)
11 | {
12 | foreach (var type in module.Types)
13 | {
14 | if (type.IsClass && type.FullName.StartsWith("ns0"))
15 | {
16 | var classInfo = new ClassInfo
17 | {
18 | ClassName = type.FullName,
19 | Methods = type.Methods.Select(m => new MethodInfo
20 | {
21 | Name = m.Name,
22 | Parameters = m.Parameters.Select(p => p.ParameterType.FullName).ToList(),
23 | ReturnType = m.ReturnType.FullName,
24 | Body = m.HasBody ? string.Join(" ", m.Body.Instructions.Select(i => i.OpCode.Code.ToString())) : string.Empty
25 | }).ToList(),
26 | Fields = type.Fields.Select(f => f.Name).ToList(),
27 | Properties = type.Properties.Select(p => p.Name).ToList()
28 | };
29 | classes[classInfo.ClassName] = classInfo;
30 | }
31 | }
32 | }
33 |
34 | return classes;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/Labeling.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class Labeling
4 | {
5 | public static void ManualLabeling(List pairs)
6 | {
7 | // Implement a manual labeling interface or tool
8 | // For simplicity, this is a placeholder for manual labeling
9 | foreach (var pair in pairs)
10 | {
11 | Console.WriteLine($"Old Class: {pair.OldClass.ClassName}, New Class: {pair.NewClass.ClassName}");
12 | Console.WriteLine("Are these the same class? (y/n)");
13 | var input = Console.ReadLine();
14 | pair.IsSameClass = input.ToLower() == "y";
15 | }
16 | }
17 |
18 | public static void AutoLabeling(List pairs)
19 | {
20 | // Implement heuristic rules for automatic labeling
21 | foreach (var pair in pairs)
22 | {
23 | pair.IsSameClass = pair.OldClass.ClassName == pair.NewClass.ClassName;
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/MappingTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/MethodInfo.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class MethodInfo
4 | {
5 | public string Name { get; set; }
6 | public List Parameters { get; set; }
7 | public string ReturnType { get; set; }
8 | public string Body { get; set; }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/PairGenerator.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | public class PairGenerator
4 | {
5 | public static List GeneratePairs(Dictionary oldClasses, Dictionary newClasses)
6 | {
7 | var pairs = new List();
8 |
9 | foreach (var oldClass in oldClasses.Values)
10 | {
11 | foreach (var newClass in newClasses.Values)
12 | {
13 | pairs.Add(new ClassPair { OldClass = oldClass, NewClass = newClass });
14 | }
15 | }
16 |
17 | return pairs;
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/Program.cs:
--------------------------------------------------------------------------------
1 | namespace MappingTest
2 | {
3 | class Program
4 | {
5 | static void Main(string[] args)
6 | {
7 | if (args.Length != 2)
8 | {
9 | Console.WriteLine("Usage: CompareExeVersions ");
10 | return;
11 | }
12 |
13 | string oldExePath = args[0];
14 | string newExePath = args[1];
15 |
16 | var oldClasses = Extractor.GetClassesFromAssembly(oldExePath);
17 | var newClasses = Extractor.GetClassesFromAssembly(newExePath);
18 |
19 | var pairs = PairGenerator.GeneratePairs(oldClasses, newClasses);
20 |
21 | Labeling.AutoLabeling(pairs);
22 |
23 | foreach (var pair in pairs)
24 | {
25 | Console.WriteLine($"Old Class: {pair.OldClass.ClassName}, New Class: {pair.NewClass.ClassName}, IsSameClass: {pair.IsSameClass}");
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/MappingTest/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "MappingTest": {
4 | "commandName": "Project",
5 | "commandLineArgs": "\"D:\\Programs\\Run8Studios\\Run8 Train Simulator V3\\old\\Run-8 Train Simulator V3_update_11_renamed.exe\" \"D:\\Programs\\Run8Studios\\Run8 Train Simulator V3\\old\\Run-8 Train Simulator V3_update_12_cleaned.exe\""
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/Class141.cs:
--------------------------------------------------------------------------------
1 | namespace ModelLoaderTest
2 | {
3 | public sealed class Class141
4 | {
5 | //public Texture2D texture2D_0;
6 | public string texture2D_0;
7 |
8 | //public Texture2D texture2D_1;
9 | public string texture2D_1;
10 |
11 | //public Texture2D texture2D_2;
12 | public string texture2D_2;
13 |
14 | public int BaseVertexLocation;
15 |
16 | public int StartIndexLocation;
17 |
18 | public int IndexCountPerInstance;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/Class251.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 | using LibRun8.Util;
3 |
4 | namespace ModelLoaderTest
5 | {
6 | public class Class251
7 | {
8 | public void method_0(float float_0)
9 | {
10 | if (this.quaternion_0.Length < 2)
11 | {
12 | this.quaternion_1 = Quaternion.Identity;
13 | this.vector3_1 = Vector3.Zero;
14 | return;
15 | }
16 | int num = Utils.Clamp((int)(float_0 * (float)this.quaternion_0.Length - 2f), 0, this.quaternion_0.Length - 2);
17 | int num2 = Utils.Clamp(num + 1, 0, this.quaternion_0.Length - 1);
18 | Quaternion quaternion = this.quaternion_0[num];
19 | Quaternion quaternion2 = this.quaternion_0[num2];
20 | Vector3 vector = this.vector3_0[num];
21 | Vector3 vector2 = this.vector3_0[num2];
22 | float num3 = 1f / (float)(this.quaternion_0.Length - 1);
23 | float num4 = Utils.Lerp(0f, 1f, float_0 - num3 * (float)num / num3);
24 | if (quaternion != quaternion2)
25 | {
26 | this.quaternion_1 = Quaternion.Lerp(quaternion, quaternion2, num4);
27 | }
28 | else
29 | {
30 | this.quaternion_1 = quaternion;
31 | }
32 | this.vector3_1 = Vector3.Lerp(vector, vector2, num4);
33 | }
34 |
35 | internal Quaternion[] quaternion_0;
36 |
37 | internal Vector3[] vector3_0;
38 |
39 | internal Quaternion quaternion_1;
40 |
41 | internal Vector3 vector3_1;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/Class252.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace ModelLoaderTest
4 | {
5 | public class Class252
6 | {
7 | // Token: 0x06001379 RID: 4985 RVA: 0x0000CC48 File Offset: 0x0000AE48
8 | public void Dispose()
9 | {
10 | //this.buffer_0.Dispose();
11 | //this.buffer_1.Dispose();
12 | }
13 |
14 | // Token: 0x0600137A RID: 4986 RVA: 0x0007DDC4 File Offset: 0x0007BFC4
15 | public void method_1(float float_0)
16 | {
17 | Vector3 vector = Vector3.Transform(Vector3.ForwardRH, this.class252_0.quaternion_0);
18 | Vector3 vector2 = Vector3.Transform(Vector3.Up, this.class252_0.quaternion_0);
19 | Vector3 vector3 = Vector3.Transform(Vector3.Right, this.class252_0.quaternion_0);
20 | //this.vector3_2 != Vector3.Zero;
21 | if (this.class251_0 != null)
22 | {
23 | this.class251_0.method_0(float_0);
24 | this.quaternion_0 = this.class252_0.quaternion_0 * this.class251_0.quaternion_1 * this.quaternion_2 * this.RotationMatrix;
25 | this.vector3_0 = this.class252_0.vector3_0;
26 | this.vector3_0 += vector3 * this.class251_0.vector3_1.X;
27 | this.vector3_0 += vector2 * this.class251_0.vector3_1.Y;
28 | this.vector3_0 += vector * this.class251_0.vector3_1.Z;
29 | }
30 | else
31 | {
32 | this.quaternion_0 = this.class252_0.quaternion_0;
33 | this.vector3_0 = this.class252_0.vector3_0;
34 | this.vector3_0 += vector3 * this.PositionOffset.X;
35 | this.vector3_0 += vector2 * this.PositionOffset.Y;
36 | this.vector3_0 += vector * this.PositionOffset.Z;
37 | }
38 | Vector3 vector4 = this.vector3_3 - this.class252_0.vector3_3 + this.vector3_1;
39 | this.vector3_0 += vector3 * vector4.X;
40 | this.vector3_0 += vector2 * vector4.Y;
41 | this.vector3_0 += vector * -vector4.Z;
42 | }
43 |
44 | //public Enum41 enum41_0;
45 | public bool isUshortIndexBuffer = false;
46 |
47 | public string string_0 { get; set; }
48 |
49 | public string string_1 { get; set; }
50 |
51 | //public SharpDX.Toolkit.Graphics.Buffer buffer_0;
52 | public Struct7[] VertexBuffer;
53 |
54 | //public SharpDX.Toolkit.Graphics.Buffer buffer_1;
55 |
56 | public ushort[] IndexBuffer1;
57 | public int[] IndexBuffer2;
58 |
59 | public List list_0 = new List();
60 |
61 | public Quaternion quaternion_0 { get; set; } = Quaternion.Identity;
62 |
63 | public Vector3 vector3_0 { get; set; } = Vector3.Zero;
64 |
65 | public Vector3 vector3_1 { get; set; } = Vector3.Zero;
66 |
67 | public Quaternion RotationMatrix { get; set; } = Quaternion.Identity;
68 |
69 | public Quaternion quaternion_2 { get; set; } = Quaternion.Identity;
70 |
71 | public Vector3 PositionOffset { get; set; } = Vector3.Zero;
72 |
73 | public Vector3 vector3_3 { get; set; } = Vector3.Zero;
74 |
75 | public Class251 class251_0 { get; set; }
76 |
77 | public Class252 class252_0 { get; set; }
78 |
79 | public bool bool_0 { get; set; } = true;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/ModelLoaderTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | AnyCPU;x64
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "ModelLoaderTest": {
4 | "commandName": "Project",
5 | "commandLineArgs": "\"D:\\Programs\\Run8Studios\\Run8 Train Simulator V3\\Content\\V3RailVehicles\\Body\\R8_SD40T-2_SP01.rn8\""
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/Struct7.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace ModelLoaderTest
4 | {
5 | public struct Struct7
6 | {
7 | //[VertexElement("SV_Position")]
8 | public Vector3 Position;
9 |
10 | //[VertexElement("NORMAL")]
11 | public Vector3 Normal;
12 |
13 | //[VertexElement("TEXCOORD0")]
14 | public Vector2 TexCoord0;
15 |
16 | //[VertexElement("TANGENT")]
17 | public Vector3 Tangent;
18 |
19 | //[VertexElement("BINORMAL")]
20 | public Vector3 BiNormal;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/lib/CS/Run8/ModelLoaderTest/VertexPositionNormalTexture.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Common;
2 |
3 | namespace ModelLoaderTest
4 | {
5 | public struct VertexPositionNormalTexture : IEquatable
6 | {
7 | ///
8 | /// Initializes a new instance.
9 | ///
10 | /// The position of this vertex.
11 | /// The vertex normal.
12 | /// UV texture coordinates.
13 | public VertexPositionNormalTexture(Vector3 position, Vector3 normal, Vector2 textureCoordinate)
14 | {
15 | this = default(VertexPositionNormalTexture);
16 | this.Position = position;
17 | this.Normal = normal;
18 | this.TextureCoordinate = textureCoordinate;
19 | }
20 |
21 | public bool Equals(VertexPositionNormalTexture other)
22 | {
23 | return this.Position.Equals(other.Position) && this.Normal.Equals(other.Normal) && this.TextureCoordinate.Equals(other.TextureCoordinate);
24 | }
25 |
26 | public override bool Equals(object obj)
27 | {
28 | return !object.ReferenceEquals(null, obj) && obj is VertexPositionNormalTexture && this.Equals((VertexPositionNormalTexture)obj);
29 | }
30 |
31 | public override int GetHashCode()
32 | {
33 | int num = this.Position.GetHashCode();
34 | num = (num * 397) ^ this.Normal.GetHashCode();
35 | return (num * 397) ^ this.TextureCoordinate.GetHashCode();
36 | }
37 |
38 | public static bool operator ==(VertexPositionNormalTexture left, VertexPositionNormalTexture right)
39 | {
40 | return left.Equals(right);
41 | }
42 |
43 | public static bool operator !=(VertexPositionNormalTexture left, VertexPositionNormalTexture right)
44 | {
45 | return !left.Equals(right);
46 | }
47 |
48 | public override string ToString()
49 | {
50 | return string.Format("Position: {0}, Normal: {1}, Texcoord: {2}", this.Position, this.Normal, this.TextureCoordinate);
51 | }
52 |
53 | ///
54 | /// XYZ position.
55 | ///
56 | //[VertexElement("SV_Position")]
57 | public Vector3 Position;
58 |
59 | ///
60 | /// The vertex normal.
61 | ///
62 | //[VertexElement("NORMAL")]
63 | public Vector3 Normal;
64 |
65 | ///
66 | /// UV texture coordinates.
67 | ///
68 | //[VertexElement("TEXCOORD0")]
69 | public Vector2 TextureCoordinate;
70 |
71 | ///
72 | /// Defines structure byte size.
73 | ///
74 | public static readonly int Size = 32;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/CS/Run8/R8Explorer/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace R8Explorer
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | menuStrip1 = new MenuStrip();
32 | fileToolStripMenuItem = new ToolStripMenuItem();
33 | openToolStripMenuItem = new ToolStripMenuItem();
34 | menuStrip1.SuspendLayout();
35 | SuspendLayout();
36 | //
37 | // menuStrip1
38 | //
39 | menuStrip1.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem });
40 | menuStrip1.Location = new Point(0, 0);
41 | menuStrip1.Name = "menuStrip1";
42 | menuStrip1.Size = new Size(800, 24);
43 | menuStrip1.TabIndex = 0;
44 | menuStrip1.Text = "menuStrip1";
45 | //
46 | // fileToolStripMenuItem
47 | //
48 | fileToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { openToolStripMenuItem });
49 | fileToolStripMenuItem.Name = "fileToolStripMenuItem";
50 | fileToolStripMenuItem.Size = new Size(37, 20);
51 | fileToolStripMenuItem.Text = "File";
52 | //
53 | // openToolStripMenuItem
54 | //
55 | openToolStripMenuItem.Name = "openToolStripMenuItem";
56 | openToolStripMenuItem.Size = new Size(180, 20);
57 | openToolStripMenuItem.Text = "Open";
58 | openToolStripMenuItem.Click += openToolStripMenuItem_Click;
59 | //
60 | // MainForm
61 | //
62 | AutoScaleDimensions = new SizeF(7F, 15F);
63 | AutoScaleMode = AutoScaleMode.Font;
64 | BackColor = Color.FromArgb(18, 18, 18);
65 | ClientSize = new Size(800, 450);
66 | Controls.Add(menuStrip1);
67 | MainMenuStrip = menuStrip1;
68 | Name = "MainForm";
69 | Text = "Run8 Explorer";
70 | menuStrip1.ResumeLayout(false);
71 | menuStrip1.PerformLayout();
72 | ResumeLayout(false);
73 | PerformLayout();
74 | }
75 |
76 | #endregion
77 |
78 | private MenuStrip menuStrip1;
79 | private ToolStripMenuItem fileToolStripMenuItem;
80 | private ToolStripMenuItem openToolStripMenuItem;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/lib/CS/Run8/R8Explorer/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 |
3 | namespace R8Explorer
4 | {
5 | public partial class MainForm : Form
6 | {
7 | public MainForm()
8 | {
9 | InitializeComponent();
10 | }
11 |
12 | private void openToolStripMenuItem_Click(object sender, EventArgs e)
13 | {
14 | // open file picker
15 | OpenFileDialog openFileDialog = new OpenFileDialog();
16 | openFileDialog.Filter = FileFilterManager.GetOpenFileDialogFilter();
17 | openFileDialog.Title = "Open Run8 Train Simulator File";
18 | var res = openFileDialog.ShowDialog();
19 |
20 | if (res == DialogResult.OK)
21 | {
22 | // open file
23 | // Process.Start(openFileDialog.FileName);
24 | MessageBox.Show("Opening file: " + openFileDialog.FileName);
25 | }
26 |
27 | openFileDialog.Dispose();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/CS/Run8/R8Explorer/Program.cs:
--------------------------------------------------------------------------------
1 | namespace R8Explorer
2 | {
3 | internal static class Program
4 | {
5 | ///
6 | /// The main entry point for the application.
7 | ///
8 | [STAThread]
9 | static void Main()
10 | {
11 | // To customize application configuration such as set high DPI settings or default font,
12 | // see https://aka.ms/applicationconfiguration.
13 | ApplicationConfiguration.Initialize();
14 | Application.Run(new MainForm());
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/R8Explorer/R8Explorer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | net6.0-windows
6 | enable
7 | true
8 | enable
9 | AnyCPU;x64
10 |
11 |
12 |
--------------------------------------------------------------------------------
/lib/CS/Run8/R8Explorer/Run8Version.cs:
--------------------------------------------------------------------------------
1 | namespace R8Explorer
2 | {
3 | public enum Run8Version
4 | {
5 | V3,
6 | V2,
7 | Any
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/lib/CS/Run8/RN8ToObj/ColladaConverter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | AnyCPU;x64
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/lib/CS/Run8/RN8ToObj/Program.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Formats;
2 |
3 | namespace RN8ToDae
4 | {
5 | internal class Program
6 | {
7 | static int Main(string[] args)
8 | {
9 | if (args.Length == 0)
10 | {
11 | Console.WriteLine("No file specified");
12 | return 1;
13 | }
14 |
15 | string inputFilePath = args[0];
16 | string inputFileName, inputFileExt, inputFileWithoutExt;
17 |
18 | if (!File.Exists(inputFilePath))
19 | {
20 | Console.WriteLine("File does not exist: " + inputFilePath);
21 | return 1;
22 | }
23 |
24 | inputFileName = Path.GetFileName(inputFilePath);
25 | inputFileExt = Path.GetExtension(inputFilePath);
26 | inputFileWithoutExt = Path.GetFileNameWithoutExtension(inputFilePath);
27 |
28 | if (inputFileExt.ToLower() != ".rn8")
29 | {
30 | Console.WriteLine("File is not a .rn8 file: " + inputFilePath);
31 | return 1;
32 | }
33 |
34 | try
35 | {
36 | Model model = Model.Read(inputFilePath);
37 | model.WriteCollada(inputFileWithoutExt + ".dae");
38 | Console.WriteLine("Conversion of " + inputFileName + ": OK");
39 | return 0;
40 | }
41 | catch (Exception ex)
42 | {
43 | Console.WriteLine("Conversion of " + inputFileName + ": FAILED");
44 | Console.WriteLine(ex.Message);
45 | return 1;
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/CS/Run8/RN8ToObj/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "RN8ToObj": {
4 | "commandName": "Project",
5 | "commandLineArgs": "\"E:\\Program Files\\Run8Studios\\Run8 Train Simulator V3\\Content\\V3RailVehicles\\Body\\R8_C449W_BNSF04.rn8\""
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/Test/Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | AnyCPU;x64
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lib/CS/Run8/TextureTools/Program.cs:
--------------------------------------------------------------------------------
1 | using LibRun8.Util;
2 | using System.CommandLine;
3 |
4 | namespace TextureTool
5 | {
6 | internal class Program
7 | {
8 | static async Task Main(string[] args)
9 | {
10 | var rootCommand = new RootCommand("Run8 Texture Tool");
11 | var decryptCommand = new Command("decrypt", "Convert tx8 to dds");
12 | var encryptCommand = new Command("encrypt", "Convert dds to tx8");
13 |
14 | var fileArgument = new Argument("file", "File to convert");
15 | decryptCommand.Add(fileArgument);
16 | encryptCommand.Add(fileArgument);
17 |
18 | rootCommand.Add(decryptCommand);
19 | rootCommand.Add(encryptCommand);
20 |
21 | decryptCommand.SetHandler((file) =>
22 | {
23 | try
24 | {
25 | Decrypt(file);
26 | } catch(Exception e)
27 | {
28 | Console.WriteLine("Decryption of file '" + file.Name + "' failed: " + e.Message);
29 | }
30 | },
31 | fileArgument);
32 |
33 | encryptCommand.SetHandler((file) =>
34 | {
35 | try
36 | {
37 | Encrypt(file);
38 | }
39 | catch (Exception e)
40 | {
41 | Console.WriteLine("Encryption of file '" + file.Name + "' failed: " + e.Message);
42 | }
43 | },
44 | fileArgument);
45 |
46 | return await rootCommand.InvokeAsync(args);
47 | }
48 |
49 | private static void Decrypt(FileInfo file)
50 | {
51 | Texture.Decrypt(file);
52 | }
53 |
54 | private static void Encrypt(FileInfo file)
55 | {
56 | Texture.Encrypt(file);
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/lib/CS/Run8/TextureTools/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "TextureTool": {
4 | "commandName": "Project",
5 | "commandLineArgs": "decrypt \"E:\\Run8Studios\\Run8 Train Simulator V3\\Content\\V3RailVehicles\\Body\\R8_BethgonII_BNSF01_0.tx8\""
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/lib/CS/Run8/TextureTools/TextureTool.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | AnyCPU;x64
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/misc/README.md:
--------------------------------------------------------------------------------
1 | other random bs
--------------------------------------------------------------------------------
/misc/ksy/README.md:
--------------------------------------------------------------------------------
1 | kaitai structs
2 |
--------------------------------------------------------------------------------
/misc/ksy/compile.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | kaitai-struct-compiler -t python -d lib_run8\kaitai --python-package lib_run8.kaitai ksy\*.ksy
--------------------------------------------------------------------------------
/misc/ksy/gen_docs.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | for %%f in (ksy\*.ksy) do (
4 | python generate_docs.py "%%f" "..\..\docs"
5 | )
--------------------------------------------------------------------------------
/misc/ksy/ksy/ai_signal_database.ksy:
--------------------------------------------------------------------------------
1 | doc: Contains a list of AI Signals
2 | meta:
3 | id: ai_signal_database
4 | title: AISignalDatabase (AISignalDatabase.r8)
5 | application: Run8 Train Simulator
6 | file-extension: r8
7 | endian: le
8 | imports:
9 | - common
10 | seq:
11 | - id: reserved
12 | type: s4
13 | - id: num_entries
14 | type: s4
15 | - id: entries
16 | type: ai_signal
17 | repeat: expr
18 | repeat-expr: num_entries
19 |
20 | types:
21 | ai_signal:
22 | seq:
23 | - id: reserved
24 | type: s4
25 | - id: num_entries
26 | type: s4
27 | - id: entries
28 | type: s4
29 | repeat: expr
30 | repeat-expr: num_entries
31 | - id: bool1
32 | type: common::boolean
33 | - id: int1
34 | type: s4
35 | - id: int2
36 | type: s4
37 | - id: bool2
38 | type: common::boolean
39 | - id: class_341_1
40 | type: class_341
41 | if: bool2.is_true
42 | doc: c:Only if bool2 is true
43 | - id: bool3
44 | type: common::boolean
45 | - id: class_341_2
46 | type: class_341
47 | if: bool3.is_true
48 | doc: c:Only if bool3 is true
49 | class_341:
50 | seq:
51 | - id: int1
52 | type: s4
53 | - id: int2
54 | type: s4
55 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/ai_special_locations.ksy:
--------------------------------------------------------------------------------
1 | doc: Contains a list of AI Special Locations
2 | meta:
3 | id: ai_special_locations
4 | title: AISpecialLocations (AISpecialLocations.r8)
5 | application: Run8 Train Simulator
6 | file-extension: r8
7 | endian: le
8 | imports:
9 | - common
10 | seq:
11 | - id: reserved
12 | type: s4
13 | - id: num_entries
14 | type: s4
15 | - id: entries
16 | type: ai_special_location
17 | repeat: expr
18 | repeat-expr: num_entries
19 |
20 | types:
21 | ai_special_location:
22 | seq:
23 | - id: reserved
24 | type: s4
25 | - id: name
26 | type: common::r8string
27 | - id: type
28 | type: u1
29 | enum: ai_special_location_type
30 | - id: int1
31 | type: s4
32 | - id: int2
33 | type: s4
34 | - id: int3
35 | type: s4
36 | - id: float1
37 | type: f4
38 | - id: int4
39 | type: s4
40 | - id: bool1
41 | type: common::boolean
42 |
43 | enums:
44 | ai_special_location_type:
45 | 0: spawn_point
46 | 1: crew_change
47 | 2: crew_change_and_hold
48 | 3: passenger
49 | 4: passenger_crew_change
50 | 5: passenger_crew_change_and_hold
51 | 6: reliquish
52 | 7: passenger_reliquish
53 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/ai_track_speed_database.ksy:
--------------------------------------------------------------------------------
1 | doc: Contains a list of AI Track Speeds
2 | meta:
3 | id: ai_track_speed_database
4 | title: AITrackSpeedDatabase (AITrackSpeedDatabase.r8)
5 | application: Run8 Train Simulator
6 | file-extension: r8
7 | endian: le
8 | imports:
9 | - common
10 | seq:
11 | - id: reserved
12 | type: s4
13 | - id: num_entries
14 | type: s4
15 | - id: entries
16 | type: ai_track_speed
17 | repeat: expr
18 | repeat-expr: num_entries
19 |
20 | types:
21 | ai_track_speed:
22 | seq:
23 | - id: reserved
24 | type: s4
25 | - id: int1
26 | type: s4
27 | - id: num_entries
28 | type: s4
29 | - id: entries
30 | type: class_322
31 | repeat: expr
32 | repeat-expr: num_entries
33 | class_322:
34 | seq:
35 | - id: reserved
36 | type: s4
37 | - id: int1
38 | type: s4
39 | - id: int2
40 | type: s4
41 | - id: int3
42 | type: s4
43 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/common.ksy:
--------------------------------------------------------------------------------
1 | doc: "Common Types\n\n
2 | ## Encoding Strings\n
3 | ```c#\n
4 | string s = \"1ST COAST RECYCLING\";\n
5 | byte[] bytes = Encoding.UTF8.GetBytes(s);\n
6 | byte[] encoded = new byte[bytes.Length * 2];\n
7 | int num = 0;\n
8 | for (int i = 0; i < bytes.Length; i++)\n
9 | {\n
10 | \tencoded[num++] = (byte)(bytes[i] >> 4);\n
11 | \tencoded[num++] = (byte)(bytes[i] << 4);\n
12 | }\n
13 | ```\n\n
14 | ## Decoding Strings\n
15 | ```c#\n
16 | byte[] encoded = ;\n
17 | byte[] decodedBytes = new byte[encoded.Length / 2];\n
18 | int num = 0;\n
19 | for (int i = 0; i < decodedBytes.Length; i++)\n
20 | {\n
21 | \tdecodedBytes[i] |= (byte)(encoded[num++] << 4);\n
22 | \tdecodedBytes[i] |= (byte)(encoded[num++] >> 4);\n
23 | }\n\n
24 | string decodedString = Encoding.UTF8.GetString(decodedBytes);\n
25 | ```"
26 | meta:
27 | id: common
28 | title: Common
29 | application: Run8 Train Simulator V3
30 | endian: le
31 | ks-opaque-types: true
32 | types:
33 | r8string:
34 | doc: Run8 specific string format
35 | seq:
36 | - id: len_value
37 | type: s4
38 | doc: d:Length of the encoded string, x2 len of decoded string
39 | - id: value
40 | size: len_value
41 | process: lib_run8.string_utils.decode_run8_string(len_value)
42 | doc: d:Decoded string
43 | cs_string:
44 | doc: C# style string
45 | seq:
46 | - id: len
47 | type: u1
48 | doc: d:Length of the string as a 7 bit encoded int
49 | - id: value
50 | type: str
51 | encoding: UTF-8
52 | size: len
53 | vector2:
54 | seq:
55 | - id: x
56 | type: f4
57 | - id: y
58 | type: f4
59 | vector3:
60 | seq:
61 | - id: x
62 | type: f4
63 | - id: y
64 | type: f4
65 | - id: z
66 | type: f4
67 | tilexz:
68 | seq:
69 | - id: x
70 | type: s4
71 | - id: z
72 | type: s4
73 | matrix4:
74 | seq:
75 | - id: m11
76 | type: f4
77 | - id: m12
78 | type: f4
79 | - id: m13
80 | type: f4
81 | - id: m14
82 | type: f4
83 | - id: m21
84 | type: f4
85 | - id: m22
86 | type: f4
87 | - id: m23
88 | type: f4
89 | - id: m24
90 | type: f4
91 | - id: m31
92 | type: f4
93 | - id: m32
94 | type: f4
95 | - id: m33
96 | type: f4
97 | - id: m34
98 | type: f4
99 | - id: m41
100 | type: f4
101 | - id: m42
102 | type: f4
103 | - id: m43
104 | type: f4
105 | - id: m44
106 | type: f4
107 | color:
108 | seq:
109 | - id: a
110 | type: u1
111 | - id: r
112 | type: u1
113 | - id: g
114 | type: u1
115 | - id: b
116 | type: u1
117 | boolean:
118 | doc: This is just a bullshit stub
119 | seq:
120 | - id: value
121 | type: u1
122 | instances:
123 | is_true:
124 | value: value != 0
125 | is_false:
126 | value: value == 0
127 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/key_settings.ksy:
--------------------------------------------------------------------------------
1 | doc: Stores game keybind settings
2 | meta:
3 | id: key_settings
4 | title: Key Settings (Run8KeySettings.r8)
5 | application: Run8 Train Simulator
6 | file-extension: r8
7 | endian: le
8 | imports:
9 | - common
10 | seq:
11 | - id: reserved
12 | type: s4
13 | - id: num_settings
14 | type: s4
15 | - id: settings
16 | type: key_setting
17 | repeat: expr
18 | repeat-expr: num_settings
19 |
20 | types:
21 | key_setting:
22 | seq:
23 | - id: reserved
24 | type: s4
25 | - id: name
26 | type: common::r8string
27 | - id: enum70
28 | type: s1
29 | - id: num_keys
30 | type: s4
31 | - id: keys
32 | type: s4
33 | repeat: expr
34 | repeat-expr: num_keys
35 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/service_area_database.ksy:
--------------------------------------------------------------------------------
1 | meta:
2 | id: service_area_database
3 | title: ServiceAreaDatabase (ServiceAreaDatabase.r8)
4 | application: Run8 Train Simulator
5 | file-extension: r8
6 | endian: le
7 | imports:
8 | - common
9 | seq:
10 | - id: reserved
11 | type: s4
12 | - id: num_service_areas
13 | type: s4
14 | - id: service_areas
15 | type: service_area
16 | repeat: expr
17 | repeat-expr: num_service_areas
18 |
19 | types:
20 | service_area:
21 | seq:
22 | - id: num
23 | type: s4
24 | - id: path1
25 | type: path1
26 | if: num == 1
27 | doc: c:Only if num == 1
28 | - id: path2
29 | type: path2
30 | if: num == 2
31 | doc: c:Only if num == 2
32 | path1:
33 | seq:
34 | - id: tile_xz
35 | type: common::tilexz
36 | - id: position
37 | type: common::vector3
38 | - id: float0
39 | type: f4
40 | - id: bool0
41 | type: common::boolean
42 | - id: bool1
43 | type: common::boolean
44 | - id: bool2
45 | type: common::boolean
46 | - id: bool3
47 | type: common::boolean
48 | path2:
49 | seq:
50 | - id: tile_xz
51 | type: common::tilexz
52 | - id: position
53 | type: common::vector3
54 | - id: float0
55 | type: f4
56 | - id: class646
57 | type: class646
58 | class646:
59 | seq:
60 | - id: enum50_0
61 | type: s1
62 | - id: enum60_0
63 | type: s1
64 | - id: double1
65 | type: f8
66 | - id: double2
67 | type: f8
68 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/stars4.ksy:
--------------------------------------------------------------------------------
1 | doc: Contains a list of strings, including file paths. Strings are referenced by their index.
2 | meta:
3 | id: stars4
4 | title: Stars4 (stars4.r8)
5 | application: Run8 Train Simulator
6 | file-extension: rn8
7 | endian: le
8 | imports:
9 | - common
10 | seq:
11 | - id: reserved
12 | type: s4
13 | - id: num_entries
14 | type: s4
15 | - id: entries
16 | type: common::r8string
17 | repeat: expr
18 | repeat-expr: num_entries
19 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/tilescenery.ksy:
--------------------------------------------------------------------------------
1 | meta:
2 | id: tile_scenery
3 | title: Tile Scenery File
4 | application: Run8 Train Simulator
5 | file-extension: rn8
6 | endian: le
7 | imports:
8 | - common
9 | seq:
10 | - id: num_assets
11 | type: s4
12 | - id: assets
13 | type: asset
14 | repeat: expr
15 | repeat-expr: num_assets
16 | types:
17 | asset:
18 | seq:
19 | - id: num_decals
20 | type: s4
21 | - id: decals
22 | type: decal
23 | repeat: expr
24 | repeat-expr: num_decals
25 | - id: disregard_bounding_test
26 | type: s1
27 | - id: model_name
28 | type: common::cs_string
29 | - id: position
30 | type: common::vector3
31 | - id: rotation
32 | type: common::vector3
33 | - id: scale
34 | type: common::vector3
35 | - id: tile_xz
36 | type: common::tilexz
37 | decal:
38 | seq:
39 | - id: color_r
40 | type: f4
41 | - id: color_g
42 | type: f4
43 | - id: color_b
44 | type: f4
45 | - id: num_digits
46 | type: s4
47 | - id: digits
48 | type: digit
49 | repeat: expr
50 | repeat-expr: num_digits
51 | - id: offset
52 | type: common::vector3
53 | - id: rotation_deg
54 | type: common::vector3
55 | - id: size
56 | type: f4
57 | - id: texture_name
58 | type: common::cs_string
59 | digit:
60 | seq:
61 | - id: digit
62 | type: s4
63 |
--------------------------------------------------------------------------------
/misc/ksy/ksy/tr2.ksy:
--------------------------------------------------------------------------------
1 | meta:
2 | id: terrain_tr2
3 | title: TR2 Terrain Tile
4 | application: Run8 Train Simulator
5 | file-extension: tr2
6 | endian: le
7 | imports:
8 | - common
9 | seq:
10 | - id: texture_1
11 | type: common::cs_string
12 | - id: texture_2
13 | type: common::cs_string
14 | - id: texture_3
15 | type: common::cs_string
16 | - id: texture_4
17 | type: common::cs_string
18 | - id: chunks
19 | type: chunk_row
20 | repeat: expr
21 | repeat-expr: 25
22 | doc: d:Tile X; Tiles are 25x25 chunks
23 | - id: lon_east
24 | type: f4
25 | - id: lon_west
26 | type: f4
27 | - id: lat_north
28 | type: f4
29 | - id: lat_south
30 | type: f4
31 | types:
32 | chunk_row:
33 | seq:
34 | - id: chunks
35 | type: chunk
36 | repeat: expr
37 | repeat-expr: 25
38 | doc: d:Tile Y; Tiles are 25x25 chunks
39 | chunk:
40 | seq:
41 | - id: chunk_size
42 | type: u4
43 | doc: d:Number of elevation points in this chunk
44 | - id: elevations_row
45 | type: elevation_col
46 | repeat: expr
47 | repeat-expr: chunk_size
48 | doc: d:Chunk X
49 | elevation_col:
50 | seq:
51 | - id: elevation
52 | type: f4
53 | repeat: expr
54 | repeat-expr: _parent.chunk_size
55 | doc: d:Chunk Y
56 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/ai_signal_database.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class AiSignalDatabase(KaitaiStruct):
13 | """Contains a list of AI Signals."""
14 | def __init__(self, _io, _parent=None, _root=None):
15 | self._io = _io
16 | self._parent = _parent
17 | self._root = _root if _root else self
18 | self._read()
19 |
20 | def _read(self):
21 | self.reserved = self._io.read_s4le()
22 | self.num_entries = self._io.read_s4le()
23 | self.entries = []
24 | for i in range(self.num_entries):
25 | self.entries.append(AiSignalDatabase.AiSignal(self._io, self, self._root))
26 |
27 |
28 | class AiSignal(KaitaiStruct):
29 | def __init__(self, _io, _parent=None, _root=None):
30 | self._io = _io
31 | self._parent = _parent
32 | self._root = _root
33 | self._read()
34 |
35 | def _read(self):
36 | self.reserved = self._io.read_s4le()
37 | self.num_entries = self._io.read_s4le()
38 | self.entries = []
39 | for i in range(self.num_entries):
40 | self.entries.append(self._io.read_s4le())
41 |
42 | self.bool1 = common.Common.Boolean(self._io)
43 | self.int1 = self._io.read_s4le()
44 | self.int2 = self._io.read_s4le()
45 | self.bool2 = common.Common.Boolean(self._io)
46 | if self.bool2.is_true:
47 | self.class_341_1 = AiSignalDatabase.Class341(self._io, self, self._root)
48 |
49 | self.bool3 = common.Common.Boolean(self._io)
50 | if self.bool3.is_true:
51 | self.class_341_2 = AiSignalDatabase.Class341(self._io, self, self._root)
52 |
53 |
54 |
55 | class Class341(KaitaiStruct):
56 | def __init__(self, _io, _parent=None, _root=None):
57 | self._io = _io
58 | self._parent = _parent
59 | self._root = _root
60 | self._read()
61 |
62 | def _read(self):
63 | self.int1 = self._io.read_s4le()
64 | self.int2 = self._io.read_s4le()
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/ai_special_locations.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 | from enum import IntEnum
8 |
9 |
10 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
11 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
12 |
13 | class AiSpecialLocations(KaitaiStruct):
14 | """Contains a list of AI Special Locations."""
15 |
16 | class AiSpecialLocationType(IntEnum):
17 | spawn_point = 0
18 | crew_change = 1
19 | crew_change_and_hold = 2
20 | passenger = 3
21 | passenger_crew_change = 4
22 | passenger_crew_change_and_hold = 5
23 | reliquish = 6
24 | passenger_reliquish = 7
25 | def __init__(self, _io, _parent=None, _root=None):
26 | self._io = _io
27 | self._parent = _parent
28 | self._root = _root if _root else self
29 | self._read()
30 |
31 | def _read(self):
32 | self.reserved = self._io.read_s4le()
33 | self.num_entries = self._io.read_s4le()
34 | self.entries = []
35 | for i in range(self.num_entries):
36 | self.entries.append(AiSpecialLocations.AiSpecialLocation(self._io, self, self._root))
37 |
38 |
39 | class AiSpecialLocation(KaitaiStruct):
40 | def __init__(self, _io, _parent=None, _root=None):
41 | self._io = _io
42 | self._parent = _parent
43 | self._root = _root
44 | self._read()
45 |
46 | def _read(self):
47 | self.reserved = self._io.read_s4le()
48 | self.name = common.Common.R8string(self._io)
49 | self.type = KaitaiStream.resolve_enum(AiSpecialLocations.AiSpecialLocationType, self._io.read_u1())
50 | self.int1 = self._io.read_s4le()
51 | self.int2 = self._io.read_s4le()
52 | self.int3 = self._io.read_s4le()
53 | self.float1 = self._io.read_f4le()
54 | self.int4 = self._io.read_s4le()
55 | self.bool1 = common.Common.Boolean(self._io)
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/ai_track_speed_database.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 |
7 |
8 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
9 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
10 |
11 | class AiTrackSpeedDatabase(KaitaiStruct):
12 | """Contains a list of AI Track Speeds."""
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.reserved = self._io.read_s4le()
21 | self.num_entries = self._io.read_s4le()
22 | self.entries = []
23 | for i in range(self.num_entries):
24 | self.entries.append(AiTrackSpeedDatabase.AiTrackSpeed(self._io, self, self._root))
25 |
26 |
27 | class AiTrackSpeed(KaitaiStruct):
28 | def __init__(self, _io, _parent=None, _root=None):
29 | self._io = _io
30 | self._parent = _parent
31 | self._root = _root
32 | self._read()
33 |
34 | def _read(self):
35 | self.reserved = self._io.read_s4le()
36 | self.int1 = self._io.read_s4le()
37 | self.num_entries = self._io.read_s4le()
38 | self.entries = []
39 | for i in range(self.num_entries):
40 | self.entries.append(AiTrackSpeedDatabase.Class322(self._io, self, self._root))
41 |
42 |
43 |
44 | class Class322(KaitaiStruct):
45 | def __init__(self, _io, _parent=None, _root=None):
46 | self._io = _io
47 | self._parent = _parent
48 | self._root = _root
49 | self._read()
50 |
51 | def _read(self):
52 | self.reserved = self._io.read_s4le()
53 | self.int1 = self._io.read_s4le()
54 | self.int2 = self._io.read_s4le()
55 | self.int3 = self._io.read_s4le()
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/key_settings.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class KeySettings(KaitaiStruct):
13 | """Stores game keybind settings."""
14 | def __init__(self, _io, _parent=None, _root=None):
15 | self._io = _io
16 | self._parent = _parent
17 | self._root = _root if _root else self
18 | self._read()
19 |
20 | def _read(self):
21 | self.reserved = self._io.read_s4le()
22 | self.num_settings = self._io.read_s4le()
23 | self.settings = []
24 | for i in range(self.num_settings):
25 | self.settings.append(KeySettings.KeySetting(self._io, self, self._root))
26 |
27 |
28 | class KeySetting(KaitaiStruct):
29 | def __init__(self, _io, _parent=None, _root=None):
30 | self._io = _io
31 | self._parent = _parent
32 | self._root = _root
33 | self._read()
34 |
35 | def _read(self):
36 | self.reserved = self._io.read_s4le()
37 | self.name = common.Common.R8string(self._io)
38 | self.enum70 = self._io.read_s1()
39 | self.num_keys = self._io.read_s4le()
40 | self.keys = []
41 | for i in range(self.num_keys):
42 | self.keys.append(self._io.read_s4le())
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/service_area_database.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class ServiceAreaDatabase(KaitaiStruct):
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.reserved = self._io.read_s4le()
21 | self.num_service_areas = self._io.read_s4le()
22 | self.service_areas = []
23 | for i in range(self.num_service_areas):
24 | self.service_areas.append(ServiceAreaDatabase.ServiceArea(self._io, self, self._root))
25 |
26 |
27 | class Class646(KaitaiStruct):
28 | def __init__(self, _io, _parent=None, _root=None):
29 | self._io = _io
30 | self._parent = _parent
31 | self._root = _root
32 | self._read()
33 |
34 | def _read(self):
35 | self.enum50_0 = self._io.read_s1()
36 | self.enum60_0 = self._io.read_s1()
37 | self.double1 = self._io.read_f8le()
38 | self.double2 = self._io.read_f8le()
39 |
40 |
41 | class Path1(KaitaiStruct):
42 | def __init__(self, _io, _parent=None, _root=None):
43 | self._io = _io
44 | self._parent = _parent
45 | self._root = _root
46 | self._read()
47 |
48 | def _read(self):
49 | self.tile_xz = common.Common.Tilexz(self._io)
50 | self.position = common.Common.Vector3(self._io)
51 | self.float0 = self._io.read_f4le()
52 | self.bool0 = common.Common.Boolean(self._io)
53 | self.bool1 = common.Common.Boolean(self._io)
54 | self.bool2 = common.Common.Boolean(self._io)
55 | self.bool3 = common.Common.Boolean(self._io)
56 |
57 |
58 | class Path2(KaitaiStruct):
59 | def __init__(self, _io, _parent=None, _root=None):
60 | self._io = _io
61 | self._parent = _parent
62 | self._root = _root
63 | self._read()
64 |
65 | def _read(self):
66 | self.tile_xz = common.Common.Tilexz(self._io)
67 | self.position = common.Common.Vector3(self._io)
68 | self.float0 = self._io.read_f4le()
69 | self.class646 = ServiceAreaDatabase.Class646(self._io, self, self._root)
70 |
71 |
72 | class ServiceArea(KaitaiStruct):
73 | def __init__(self, _io, _parent=None, _root=None):
74 | self._io = _io
75 | self._parent = _parent
76 | self._root = _root
77 | self._read()
78 |
79 | def _read(self):
80 | self.num = self._io.read_s4le()
81 | if self.num == 1:
82 | self.path1 = ServiceAreaDatabase.Path1(self._io, self, self._root)
83 |
84 | if self.num == 2:
85 | self.path2 = ServiceAreaDatabase.Path2(self._io, self, self._root)
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/stars4.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class Stars4(KaitaiStruct):
13 | """Contains a list of strings, including file paths. Strings are referenced by their index."""
14 | def __init__(self, _io, _parent=None, _root=None):
15 | self._io = _io
16 | self._parent = _parent
17 | self._root = _root if _root else self
18 | self._read()
19 |
20 | def _read(self):
21 | self.reserved = self._io.read_s4le()
22 | self.num_entries = self._io.read_s4le()
23 | self.entries = []
24 | for i in range(self.num_entries):
25 | self.entries.append(common.Common.R8string(self._io))
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/terrain_tr2.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class TerrainTr2(KaitaiStruct):
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.texture_1 = common.Common.CsString(self._io)
21 | self.texture_2 = common.Common.CsString(self._io)
22 | self.texture_3 = common.Common.CsString(self._io)
23 | self.texture_4 = common.Common.CsString(self._io)
24 | self.chunks = []
25 | for i in range(25):
26 | self.chunks.append(TerrainTr2.ChunkRow(self._io, self, self._root))
27 |
28 | self.lon_east = self._io.read_f4le()
29 | self.lon_west = self._io.read_f4le()
30 | self.lat_north = self._io.read_f4le()
31 | self.lat_south = self._io.read_f4le()
32 |
33 | class Chunk(KaitaiStruct):
34 | def __init__(self, _io, _parent=None, _root=None):
35 | self._io = _io
36 | self._parent = _parent
37 | self._root = _root
38 | self._read()
39 |
40 | def _read(self):
41 | self.chunk_size = self._io.read_u4le()
42 | self.elevations_row = []
43 | for i in range(self.chunk_size):
44 | self.elevations_row.append(TerrainTr2.ElevationCol(self._io, self, self._root))
45 |
46 |
47 |
48 | class ChunkRow(KaitaiStruct):
49 | def __init__(self, _io, _parent=None, _root=None):
50 | self._io = _io
51 | self._parent = _parent
52 | self._root = _root
53 | self._read()
54 |
55 | def _read(self):
56 | self.chunks = []
57 | for i in range(25):
58 | self.chunks.append(TerrainTr2.Chunk(self._io, self, self._root))
59 |
60 |
61 |
62 | class ElevationCol(KaitaiStruct):
63 | def __init__(self, _io, _parent=None, _root=None):
64 | self._io = _io
65 | self._parent = _parent
66 | self._root = _root
67 | self._read()
68 |
69 | def _read(self):
70 | self.elevation = []
71 | for i in range(self._parent.chunk_size):
72 | self.elevation.append(self._io.read_f4le())
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/tile_scenery.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class TileScenery(KaitaiStruct):
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.num_assets = self._io.read_s4le()
21 | self.assets = []
22 | for i in range(self.num_assets):
23 | self.assets.append(TileScenery.Asset(self._io, self, self._root))
24 |
25 |
26 | class Asset(KaitaiStruct):
27 | def __init__(self, _io, _parent=None, _root=None):
28 | self._io = _io
29 | self._parent = _parent
30 | self._root = _root
31 | self._read()
32 |
33 | def _read(self):
34 | self.num_decals = self._io.read_s4le()
35 | self.decals = []
36 | for i in range(self.num_decals):
37 | self.decals.append(TileScenery.Decal(self._io, self, self._root))
38 |
39 | self.disregard_bounding_test = self._io.read_s1()
40 | self.model_name = common.Common.CsString(self._io)
41 | self.position = common.Common.Vector3(self._io)
42 | self.rotation = common.Common.Vector3(self._io)
43 | self.scale = common.Common.Vector3(self._io)
44 | self.tile_xz = common.Common.Tilexz(self._io)
45 |
46 |
47 | class Decal(KaitaiStruct):
48 | def __init__(self, _io, _parent=None, _root=None):
49 | self._io = _io
50 | self._parent = _parent
51 | self._root = _root
52 | self._read()
53 |
54 | def _read(self):
55 | self.color_r = self._io.read_f4le()
56 | self.color_g = self._io.read_f4le()
57 | self.color_b = self._io.read_f4le()
58 | self.num_digits = self._io.read_s4le()
59 | self.digits = []
60 | for i in range(self.num_digits):
61 | self.digits.append(TileScenery.Digit(self._io, self, self._root))
62 |
63 | self.offset = common.Common.Vector3(self._io)
64 | self.rotation_deg = common.Common.Vector3(self._io)
65 | self.size = self._io.read_f4le()
66 | self.texture_name = common.Common.CsString(self._io)
67 |
68 |
69 | class Digit(KaitaiStruct):
70 | def __init__(self, _io, _parent=None, _root=None):
71 | self._io = _io
72 | self._parent = _parent
73 | self._root = _root
74 | self._read()
75 |
76 | def _read(self):
77 | self.digit = self._io.read_s4le()
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/kaitai/tr2.py:
--------------------------------------------------------------------------------
1 | # This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
2 | # type: ignore
3 |
4 | import kaitaistruct
5 | from kaitaistruct import KaitaiStruct, KaitaiStream, BytesIO
6 | from lib_run8.kaitai import common
7 |
8 |
9 | if getattr(kaitaistruct, 'API_VERSION', (0, 9)) < (0, 11):
10 | raise Exception("Incompatible Kaitai Struct Python API: 0.11 or later is required, but you have %s" % (kaitaistruct.__version__))
11 |
12 | class Tr2(KaitaiStruct):
13 | def __init__(self, _io, _parent=None, _root=None):
14 | self._io = _io
15 | self._parent = _parent
16 | self._root = _root if _root else self
17 | self._read()
18 |
19 | def _read(self):
20 | self.texture_1 = common.Common.CsString(self._io)
21 | self.texture_2 = common.Common.CsString(self._io)
22 | self.texture_3 = common.Common.CsString(self._io)
23 | self.texture_4 = common.Common.CsString(self._io)
24 | self.chunks = []
25 | for i in range(25):
26 | self.chunks.append(Tr2.ChunkRow(self._io, self, self._root))
27 |
28 | self.lon_east = self._io.read_f4le()
29 | self.lon_west = self._io.read_f4le()
30 | self.lat_north = self._io.read_f4le()
31 | self.lat_south = self._io.read_f4le()
32 |
33 | class Chunk(KaitaiStruct):
34 | def __init__(self, _io, _parent=None, _root=None):
35 | self._io = _io
36 | self._parent = _parent
37 | self._root = _root
38 | self._read()
39 |
40 | def _read(self):
41 | self.chunk_size = self._io.read_u4le()
42 | self.elevations_row = []
43 | for i in range(self.chunk_size):
44 | self.elevations_row.append(Tr2.ElevationCol(self._io, self, self._root))
45 |
46 |
47 |
48 | class ChunkRow(KaitaiStruct):
49 | def __init__(self, _io, _parent=None, _root=None):
50 | self._io = _io
51 | self._parent = _parent
52 | self._root = _root
53 | self._read()
54 |
55 | def _read(self):
56 | self.chunks = []
57 | for i in range(25):
58 | self.chunks.append(Tr2.Chunk(self._io, self, self._root))
59 |
60 |
61 |
62 | class ElevationCol(KaitaiStruct):
63 | def __init__(self, _io, _parent=None, _root=None):
64 | self._io = _io
65 | self._parent = _parent
66 | self._root = _root
67 | self._read()
68 |
69 | def _read(self):
70 | self.elevation = []
71 | for i in range(self._parent.chunk_size):
72 | self.elevation.append(self._io.read_f4le())
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/string_utils.py:
--------------------------------------------------------------------------------
1 | from kaitaistruct import KaitaiStruct
2 |
3 |
4 | class DecodeRun8String(KaitaiStruct):
5 | def __init__(self, len_buf):
6 | super().__init__(len_buf)
7 | self.len = len_buf
8 |
9 | def decode(self, data: bytes) -> str:
10 | size = self.len // 2
11 | array = bytearray(size)
12 | num = 0
13 | for i in range(size):
14 | array[i] |= data[num] << 4
15 | num += 1
16 | array[i] |= data[num] >> 4
17 | num += 1
18 | return array.decode("utf8")
19 |
--------------------------------------------------------------------------------
/misc/ksy/lib_run8/visualizer.py:
--------------------------------------------------------------------------------
1 | # converted to python from ruby by chatgpt
2 | # Original source: https://github.com/kaitai-io/kaitai_struct_visualizer/blob/master/lib/kaitai/struct/visualizer/obj_to_h.rb
3 |
4 | from kaitaistruct import KaitaiStruct
5 |
6 |
7 | class KaitaiStructVisualizer:
8 | @staticmethod
9 | def obj_to_h(obj):
10 | if isinstance(obj, (bool, int, float, type(None))):
11 | return obj
12 | elif isinstance(obj, str):
13 | try:
14 | obj.encode("ascii")
15 | return obj
16 | except UnicodeEncodeError:
17 | return " ".join(f"{ord(c):02X}" for c in obj)
18 | elif isinstance(obj, list):
19 | return [KaitaiStructVisualizer.obj_to_h(x) for x in obj]
20 | elif isinstance(obj, KaitaiStruct):
21 | root = {}
22 | for attr in dir(obj):
23 | if not attr.startswith("_") and not callable(getattr(obj, attr)):
24 | value = getattr(obj, attr)
25 | v = KaitaiStructVisualizer.obj_to_h(value)
26 | if v is not None:
27 | root[attr] = v
28 | return root
29 | else:
30 | print(type(obj).__name__)
31 | return f"OPAQUE ({type(obj).__name__})"
32 |
--------------------------------------------------------------------------------
/misc/terrain_exporter/rename.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | dir_path = Path("heightmaps")
4 |
5 | for file in dir_path.glob("*.bin"):
6 | name = file.name
7 | split, y = name.split(".")[0].split("Y")
8 | x = split.split("X")[1]
9 |
10 | # new name should be x_y + ext
11 | new_name = f"{x}_{y}.bin"
12 | file.rename(dir_path / new_name)
13 |
--------------------------------------------------------------------------------
/misc/terrain_exporter/view.py:
--------------------------------------------------------------------------------
1 | import struct
2 | import tkinter as tk
3 | from tkinter import filedialog, messagebox
4 |
5 | import matplotlib.pyplot as plt
6 | import numpy as np
7 | from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
8 | from matplotlib.figure import Figure
9 |
10 |
11 | class ImageViewer:
12 | def __init__(self, root):
13 | self.root = root
14 | root.title("F32 Image Viewer")
15 | root.geometry("800x600")
16 |
17 | # Create matplotlib figure
18 | self.figure = Figure(figsize=(8, 6))
19 | self.ax = self.figure.add_subplot(111)
20 | self.canvas = FigureCanvasTkAgg(self.figure, master=root)
21 | self.canvas.draw()
22 | self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
23 |
24 | # Add open button
25 | open_button = tk.Button(root, text="Open File", command=self.open_file)
26 | open_button.pack(pady=5)
27 |
28 | def read_f32_image(self, file_path):
29 | with open(file_path, "rb") as f:
30 | # Read width and height from header (2 int32s)
31 | width, height = struct.unpack("ii", f.read(8))
32 |
33 | # read bounds (4 float 32s)
34 | bounds = struct.unpack("ffff", f.read(16))
35 |
36 | # Read the rest as float32 data
37 | data = np.fromfile(f, dtype=np.float32)
38 |
39 | if width * height != len(data):
40 | raise ValueError(f"File data length {len(data)} doesn't match dimensions {width}x{height}")
41 |
42 | return data.reshape(height, width)
43 |
44 | def open_file(self):
45 | file_path = filedialog.askopenfilename(title="Open F32 Image", filetypes=[("Binary Files", "*.bin")])
46 |
47 | if file_path:
48 | try:
49 | image_data = self.read_f32_image(file_path)
50 | self.display_image(image_data)
51 | except Exception as e:
52 | messagebox.showerror("Error", str(e))
53 |
54 | def display_image(self, image_data):
55 | self.ax.clear()
56 | vmin, vmax = np.percentile(image_data, [2, 98])
57 | im = self.ax.imshow(image_data, cmap="viridis", vmin=vmin, vmax=vmax)
58 | self.figure.colorbar(im, ax=self.ax, label="Intensity")
59 | self.ax.set_title(f"Image: {image_data.shape[1]}x{image_data.shape[0]}")
60 | self.canvas.draw()
61 |
62 |
63 | def main():
64 | root = tk.Tk()
65 | viewer = ImageViewer(root)
66 | root.mainloop()
67 |
68 |
69 | if __name__ == "__main__":
70 | main()
71 |
--------------------------------------------------------------------------------
/misc_scripts/binwriter.py:
--------------------------------------------------------------------------------
1 | import struct
2 | from io import SEEK_CUR
3 | from typing import BinaryIO
4 |
5 | ENDIAN_PREFIXES = ("@", "<", ">", "=", "!")
6 |
7 |
8 | class BinaryWriter:
9 | def __init__(self, buf: BinaryIO, endian: str = "<") -> None:
10 | self.buf = buf
11 | self.endian = endian
12 |
13 | def align(self) -> None:
14 | old = self.tell()
15 | new = (old + 3) & -4
16 | if new > old:
17 | self.seek(new - old, SEEK_CUR)
18 |
19 | def write(self, *args) -> int:
20 | return self.buf.write(*args)
21 |
22 | def seek(self, *args) -> int:
23 | return self.buf.seek(*args)
24 |
25 | def tell(self) -> int:
26 | return self.buf.tell()
27 |
28 | def write_string(self, value: str, encoding: str = "utf-8") -> int:
29 | """
30 | Writes a 7 bit prefixed string to the buffer.
31 | """
32 | encoded_string = value.encode(encoding)
33 | size = self.write_7bit_encoded_int(len(encoded_string))
34 | size += self.write(encoded_string)
35 |
36 | return size
37 |
38 | def write_cstring(self, value: str) -> int:
39 | return self.write_string(value + "\0")
40 |
41 | def write_7bit_encoded_int(self, value: int) -> int:
42 | while value >= 128:
43 | self.write(bytes([((value & 0x7F) | 0x80)]))
44 | value >>= 7
45 | return self.write(bytes([value]))
46 |
47 | def write_bool(self, value: bool) -> int:
48 | return self.write(struct.pack(self.endian + "b", int(value)))
49 |
50 | def write_byte(self, value: int) -> int:
51 | return self.write(struct.pack(self.endian + "b", value))
52 |
53 | def write_ubyte(self, value: int) -> int:
54 | return self.write(struct.pack(self.endian + "B", value))
55 |
56 | def write_int16(self, value: int) -> int:
57 | return self.write(struct.pack(self.endian + "h", value))
58 |
59 | def write_uint16(self, value: int) -> int:
60 | return self.write(struct.pack(self.endian + "H", value))
61 |
62 | def write_int32(self, value: int) -> int:
63 | return self.write(struct.pack(self.endian + "i", value))
64 |
65 | def write_uint32(self, value: int) -> int:
66 | return self.write(struct.pack(self.endian + "I", value))
67 |
68 | def write_int64(self, value: int) -> int:
69 | return self.write(struct.pack(self.endian + "q", value))
70 |
71 | def write_uint64(self, value: int) -> int:
72 | return self.write(struct.pack(self.endian + "Q", value))
73 |
74 | def write_float(self, value: float) -> int:
75 | return self.write(struct.pack(self.endian + "f", value))
76 |
77 | def write_double(self, value: float) -> int:
78 | return self.write(struct.pack(self.endian + "d", value))
79 |
80 | def write_struct(self, format: str, *values) -> int:
81 | if not format.startswith(ENDIAN_PREFIXES):
82 | format = self.endian + format
83 | data = struct.pack(format, *values)
84 | return self.write(data)
85 |
86 | # Aliases
87 | def write_int(self, value: int) -> int:
88 | return self.write_int32(value)
89 |
90 | def write_uint(self, value: int) -> int:
91 | return self.write_uint32(value)
92 |
--------------------------------------------------------------------------------
/misc_scripts/gen_terrain_tr2.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import math
3 |
4 | import numpy as np
5 | import rasterio
6 |
7 | from binwriter import BinaryWriter
8 |
9 | CHUNKS_X = 25
10 | CHUNKS_Z = 25
11 | TILE_X = 1026.0822 # meters
12 | TILE_Z = 844.3211 # meters
13 | CHUNK_SIZE_X = TILE_X / CHUNKS_X
14 | CHUNK_SIZE_Z = TILE_Z / CHUNKS_Z
15 |
16 |
17 | def main(file: str):
18 | with rasterio.open("./tiles/0_1.tif") as heightmap:
19 | height_values = heightmap.read(1)
20 |
21 | HIXELS = height_values.shape[1] // CHUNKS_Z
22 | print(f"Hixels per chunk per side: {HIXELS}")
23 |
24 | x_points_required = CHUNKS_X * HIXELS
25 | z_points_required = CHUNKS_Z * HIXELS
26 |
27 | x_points_available = height_values.shape[0]
28 | z_points_available = height_values.shape[1]
29 |
30 | if x_points_available < x_points_required:
31 | print(f"Not enough x points available: {x_points_available} < {x_points_required}")
32 | else:
33 | print(f"X points available: {x_points_available} >= {x_points_required}")
34 |
35 | if z_points_available < z_points_required:
36 | print(f"Not enough z points available: {z_points_available} < {z_points_required}")
37 | else:
38 | print(f"Z points available: {z_points_available} >= {z_points_required}")
39 |
40 | min_x_value = np.amin(height_values, axis=0)
41 | min_z_value = np.amin(height_values, axis=1)
42 |
43 | min_x_value = np.min(min_x_value)
44 | min_z_value = np.min(min_z_value)
45 |
46 | with open(file, "wb") as f:
47 | writer = BinaryWriter(f)
48 |
49 | # writer texture names
50 | writer.write_cstring("sandy")
51 | writer.write_cstring("jwg_greenGrass")
52 | writer.write_cstring("jwg_cameron02")
53 | writer.write_cstring("jwg_goldenGrass")
54 |
55 | for x in range(CHUNKS_X):
56 | for z in range(CHUNKS_Z):
57 | writer.write_int32(HIXELS)
58 | for cx in range(HIXELS):
59 | for cz in range(HIXELS):
60 | x_idx = x * HIXELS + cx
61 | z_idx = z * HIXELS + cz
62 |
63 | if x_idx >= x_points_available or z_idx >= z_points_available:
64 | value = min_x_value
65 | else:
66 | value = height_values[x_idx, z_idx]
67 | if value < 0:
68 | print("oops")
69 | value = math.fabs(value)
70 | writer.write_float(value)
71 |
72 |
73 | if __name__ == "__main__":
74 | parser = argparse.ArgumentParser(description="Generate TR2 terrain")
75 | parser.add_argument("file", help="Output file")
76 |
77 | args = parser.parse_args()
78 |
79 | main(args.file)
80 |
--------------------------------------------------------------------------------
/misc_scripts/get_latlon_center.py:
--------------------------------------------------------------------------------
1 | def calculate_bounds_center(north, south, east, west):
2 | center_lat = (north + south) / 2
3 | center_lng = (east + west) / 2
4 | return center_lat, center_lng
5 |
6 |
7 | def calculate_size_bounds(north, south, east, west):
8 | lat_size = north - south
9 | lng_size = east - west
10 | return lat_size, lng_size
11 |
12 |
13 | north = 40.46984100341797
14 | east = -78.58444213867188
15 | south = 40.460601806640625
16 | west = -78.59439849853516
17 |
18 | print(calculate_bounds_center(north, south, east, west))
19 | print(calculate_size_bounds(north, south, east, west))
20 |
--------------------------------------------------------------------------------
/misc_scripts/obj_to_rn8.py:
--------------------------------------------------------------------------------
1 | from io import BytesIO
2 |
3 | from binwriter import BinaryWriter
4 |
5 | positions = []
6 | normals = []
7 | uvs = []
8 | vertices = []
9 |
10 | # First pass: read data
11 | with open("./test.obj", "r") as f:
12 | for line in f.readlines():
13 | line = line.strip()
14 | if not line or line.startswith("#"):
15 | continue
16 |
17 | parts = line.split()
18 | typ = parts[0]
19 |
20 | if typ == "v":
21 | # Read positions - note these are larger values than your working model
22 | x, y, z = map(float, parts[1:])
23 | # Scale down the positions to match working model scale
24 | positions.append((x, y, z))
25 | elif typ == "vt":
26 | u, v = map(float, parts[1:])
27 | uvs.append((u, v))
28 | elif typ == "vn":
29 | x, y, z = map(float, parts[1:])
30 | normals.append((x, y, z))
31 | elif typ == "f":
32 | # Process face indices
33 | for vert in parts[1:]:
34 | v_idx, t_idx, n_idx = map(lambda x: int(x) - 1, vert.split("/"))
35 | vertex = {"position": positions[v_idx], "normal": normals[n_idx], "uv": uvs[t_idx]}
36 | vertices.append(vertex)
37 |
38 | # Now write the file
39 | buf = BytesIO()
40 | writer = BinaryWriter(buf)
41 |
42 | # Write vertex count
43 | writer.write_int32(len(vertices) * 7)
44 |
45 | # Write each vertex
46 | for i, vertex in enumerate(vertices):
47 | pos = vertex["position"]
48 | norm = vertex["normal"]
49 | uv = vertex["uv"]
50 |
51 | writer.write_float(0.0) # unused
52 | writer.write_float(pos[0]) # pos x - already at correct scale
53 | writer.write_float(norm[1]) # normal y
54 | writer.write_float(pos[2]) # pos z
55 | writer.write_float(uv[0] * 4.8) # uv x
56 | writer.write_float(norm[0]) # normal x
57 | writer.write_float(0.0) # unused
58 | writer.write_float(norm[2]) # normal z
59 | writer.write_float(uv[1] * 9.6) # uv y
60 | writer.write_float(pos[1]) # pos y
61 |
62 | # Write texture count (-6 for testing)
63 | writer.write_int32(-6)
64 |
65 | # Write index buffer format (32-bit)
66 | writer.write_bool(False)
67 |
68 | # Write indices - just sequential since we expanded vertices
69 | index_count = len(vertices)
70 | writer.write_int32(index_count)
71 | for i in range(index_count):
72 | writer.write_int32(i)
73 |
74 | # Write definition count
75 | writer.write_int32(9)
76 |
77 | with open("./R8_Caboose_c509_SP01.rn8", "wb") as f:
78 | f.write(buf.getvalue())
79 |
--------------------------------------------------------------------------------
/misc_scripts/parse_tr2.py:
--------------------------------------------------------------------------------
1 | import argparse
2 |
3 | from binreader import BinaryReader
4 |
5 |
6 | def main(file):
7 | with open(file, "rb") as f:
8 | reader = BinaryReader(f)
9 |
10 | all_points = []
11 |
12 | print(reader.read_cs_string())
13 | print(reader.read_cs_string())
14 | print(reader.read_cs_string())
15 | print(reader.read_cs_string())
16 |
17 | # read chunks
18 | for x in range(25):
19 | for y in range(25):
20 | # read chunk hixels
21 | hixels = reader.read_int32()
22 | print(f"{x},{y} = {hixels}")
23 | for cx in range(hixels):
24 | for cy in range(hixels):
25 | value = reader.read_float()
26 | # print(f"{x},{y},{cx},{cy} = {value}")
27 | all_points.append(value)
28 | print(f"Total Points: {len(all_points)}")
29 |
30 |
31 | if __name__ == "__main__":
32 | parser = argparse.ArgumentParser(description="Parse TR2 terrain")
33 | parser.add_argument("file", help="Input file")
34 |
35 | args = parser.parse_args()
36 |
37 | main(args.file)
38 |
--------------------------------------------------------------------------------
/misc_scripts/skydome_test.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import hashlib
3 | from pathlib import Path
4 |
5 | from binreader import BinaryReader
6 |
7 |
8 | def compute_file_hash(filepath: str) -> str:
9 | md5 = hashlib.md5()
10 | with open(filepath, "rb") as f:
11 | for chunk in iter(lambda: f.read(4096), b""):
12 | md5.update(chunk)
13 |
14 | return md5.hexdigest()
15 |
16 |
17 | def main(folder_path: str):
18 | exe_path = Path(folder_path, "Run-8 Train Simulator V3.exe")
19 | skydome_path = Path(folder_path, "Content", "Misc", "SkyDomeData.rn8")
20 |
21 | if not exe_path.exists():
22 | raise FileNotFoundError(f"Could not find Run-8 Train Simulator V3.exe at {exe_path}")
23 |
24 | if not skydome_path.exists():
25 | raise FileNotFoundError(f"Could not find SkyDomeData.rn8 at {skydome_path}")
26 |
27 | file_hash = compute_file_hash(exe_path).encode("utf-8")
28 |
29 | with open(skydome_path, "rb") as f:
30 | size = f.seek(0, 2)
31 | assert size == 38888, f"Expected 38888 bytes, got {size} bytes"
32 | f.seek(0)
33 |
34 | reader = BinaryReader(f)
35 | data = []
36 | hash_data = bytearray(len(file_hash))
37 |
38 | i = 0
39 | while i < 9722:
40 | data.append(reader.read_int32())
41 | i += 1
42 |
43 | num = data[17] # 17 is the index of the file hash length
44 | assert num == len(file_hash), "Expected index 17 to be the length of the file hash"
45 |
46 | i = 0
47 | while i < num:
48 | num2 = data[i + 18]
49 | hash_data[i] = data[num2]
50 | i += 1
51 |
52 | hash_data = bytes(hash_data)
53 | assert file_hash.decode("utf-8").upper() == hash_data.decode("utf-8").upper(), "File hash does not match"
54 |
55 | print("Hashes match")
56 |
57 |
58 | if __name__ == "__main__":
59 | parser = argparse.ArgumentParser(description="SkyDomeData test parser")
60 | parser.add_argument("path", help="Path to run8v3 folder")
61 |
62 | args = parser.parse_args()
63 | main(args.path)
64 |
--------------------------------------------------------------------------------
/misc_scripts/split_geotif.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | from math import ceil
3 | from pathlib import Path
4 |
5 | import numpy as np
6 | from osgeo import gdal
7 |
8 |
9 | def split_geotiff_into_tiles(input_tiff, tile_width_meters=844.3211, tile_height_meters=1026.0822):
10 | ds = gdal.Open(input_tiff)
11 | gt = ds.GetGeoTransform()
12 | pixel_width = abs(gt[1])
13 | pixel_height = abs(gt[5])
14 |
15 | tile_width_pixels = int(ceil(tile_width_meters / pixel_width))
16 | tile_height_pixels = int(ceil(tile_height_meters / pixel_height))
17 |
18 | width = ds.RasterXSize
19 | height = ds.RasterYSize
20 |
21 | num_tiles_x = width // tile_width_pixels
22 | num_tiles_y = height // tile_height_pixels
23 |
24 | for i in range(num_tiles_y):
25 | for j in range(num_tiles_x):
26 | print(f"Processing tile {i}, {j}")
27 | x_start = j * tile_width_pixels
28 | y_start = i * tile_height_pixels
29 |
30 | output_file = Path("tiles", f"{i}_{j}.tif")
31 | output_file.parent.mkdir(exist_ok=True, parents=True)
32 | gdal.Translate(
33 | str(output_file), ds, srcWin=[x_start, y_start, tile_width_pixels, tile_height_pixels], format="GTiff"
34 | )
35 |
36 |
37 | if __name__ == "__main__":
38 | parser = argparse.ArgumentParser(description="Split a geotiff into tiles")
39 | parser.add_argument("input_tiff", help="Input geotiff file")
40 | parser.add_argument("--tile_width", type=float, default=844.3211, help="Width of each tile in meters")
41 | parser.add_argument("--tile_height", type=float, default=1026.0822, help="Height of each tile in meters")
42 |
43 | args = parser.parse_args()
44 |
45 | split_geotiff_into_tiles(args.input_tiff, args.tile_width, args.tile_height)
46 |
--------------------------------------------------------------------------------
/misc_scripts/structs.py:
--------------------------------------------------------------------------------
1 | class Vector2:
2 | def __init__(self, x: float, y: float) -> None:
3 | self.x = x
4 | self.y = y
5 |
6 | def __str__(self) -> str:
7 | return f"Vector2({self.x}, {self.y})"
8 |
9 |
10 | class Vector3:
11 | def __init__(self, x: float, y: float, z: float) -> None:
12 | self.x = x
13 | self.y = y
14 | self.z = z
15 |
16 | def __str__(self) -> str:
17 | return f"Vector3({self.x}, {self.y}, {self.z})"
18 |
19 |
20 | class Vector4:
21 | def __init__(self, x: float, y: float, z: float, w: float) -> None:
22 | self.x = x
23 | self.y = y
24 | self.z = z
25 | self.w = w
26 |
27 | def __str__(self) -> str:
28 | return f"Vector4({self.x}, {self.y}, {self.z}, {self.w})"
29 |
--------------------------------------------------------------------------------
/misc_scripts/structs2.py:
--------------------------------------------------------------------------------
1 | from construct import Array, Float32l, GreedyBytes, Int8sl, Int8ul, Int32ul, Struct, this
2 |
3 |
4 | def encode_7bit_int(length):
5 | result = bytearray()
6 | while length >= 0x80:
7 | result.append((length & 0x7F) | 0x80)
8 | length >>= 7
9 | result.append(length)
10 | return bytes(result)
11 |
12 |
13 | def build_cs_string(text):
14 | encoded_text = text.encode("utf8")
15 | length_prefix = encode_7bit_int(len(encoded_text))
16 | return length_prefix + encoded_text
17 |
18 |
19 | Chunk = Struct(
20 | "hixel_count" / Int32ul,
21 | "hixels" / Array(this.hixel_count, Array(this.hixel_count, Float32l)),
22 | )
23 |
24 | Vector3 = Struct(
25 | "x" / Float32l,
26 | "y" / Float32l,
27 | "z" / Float32l,
28 | )
29 |
30 | Vector4 = Struct(
31 | "x" / Float32l,
32 | "y" / Float32l,
33 | "z" / Float32l,
34 | "w" / Float32l,
35 | )
36 |
37 | TileIndex = Struct(
38 | "x" / Int32ul,
39 | "y" / Int32ul,
40 | )
41 |
42 | Decal = Struct(
43 | "r" / Float32l,
44 | "g" / Float32l,
45 | "b" / Float32l,
46 | "digit_count" / Int32ul,
47 | "digits" / Array(this.digit_count, Int32ul),
48 | "offset" / Vector3,
49 | "rotation" / Vector3,
50 | "size" / Float32l,
51 | "texture_name" / GreedyBytes,
52 | )
53 |
54 | SceneryAsset = Struct(
55 | "decal_count" / Int32ul,
56 | "decals" / Array(this.decal_count, Decal),
57 | "disregard_bounding_test" / Int8ul,
58 | "model_name" / GreedyBytes,
59 | "position" / Vector3,
60 | "rotation" / Vector3,
61 | "scale" / Vector3,
62 | "tile_index" / TileIndex,
63 | )
64 |
65 | TR4 = Struct(
66 | "texture_1" / GreedyBytes,
67 | "texture_2" / GreedyBytes,
68 | "texture_3" / GreedyBytes,
69 | "texture_4" / GreedyBytes,
70 | "chunks" / Array(25, Array(25, Chunk)),
71 | "east" / Float32l,
72 | "west" / Float32l,
73 | "north" / Float32l,
74 | "south" / Float32l,
75 | "veg_texture" / GreedyBytes,
76 | "scenery_asset_count" / Int32ul,
77 | "scenery_assets" / Array(this.scenery_asset_count, SceneryAsset),
78 | "plant_count" / Int32ul,
79 | "plants" / Array(this.plant_count, Vector4),
80 | "reserved" / Int32ul,
81 | "weight_map" / Int8sl,
82 | )
83 |
84 | TR2 = Struct(
85 | "texture_1" / GreedyBytes,
86 | "texture_2" / GreedyBytes,
87 | "texture_3" / GreedyBytes,
88 | "texture_4" / GreedyBytes,
89 | "chunks" / Array(25, Array(25, Chunk)),
90 | "east" / Float32l,
91 | "west" / Float32l,
92 | "north" / Float32l,
93 | "south" / Float32l,
94 | "veg_texture" / GreedyBytes,
95 | )
96 |
--------------------------------------------------------------------------------
/misc_scripts/tr4_to_tr2.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import io
3 | import zlib
4 |
5 | from binreader import BinaryReader
6 |
7 |
8 | def main(file):
9 | with open(file, "rb") as f:
10 | data = f.read()
11 | data = zlib.decompress(data, -15)
12 |
13 | reader = BinaryReader(io.BytesIO(data))
14 |
15 | print(reader.read_cs_string())
16 | print(reader.read_cs_string())
17 | print(reader.read_cs_string())
18 | print(reader.read_cs_string())
19 |
20 | chunks = []
21 | min_value = 9999999
22 | max_value = -9999999
23 |
24 | # heightmap
25 | for x in range(25):
26 | for y in range(25):
27 | # read chunk hixels
28 | hixel_count = reader.read_int32()
29 | print(f"Chunk at {x},{y} has a density of {hixel_count}x{hixel_count} points")
30 |
31 | chunk_points = []
32 | for cx in range(hixel_count):
33 | for cy in range(hixel_count):
34 | value = reader.read_float()
35 | # print(f"{x},{y},{cx},{cy} = {value}")
36 | chunk_points.append(value)
37 | min_value = min(min_value, value)
38 | max_value = max(max_value, value)
39 |
40 | print(f"Chunk at {x},{y} has {len(chunk_points)} points")
41 | chunks.append(chunk_points)
42 | print(f"Total Points: {sum([len(x) for y in chunk_points for x in chunks])}")
43 |
44 | # find the min and max values
45 | print(f"Min: {min_value}")
46 | print(f"Max: {max_value}")
47 |
48 | try:
49 | print(f"East: {reader.read_float()}")
50 | print(f"West: {reader.read_float()}")
51 | print(f"North: {reader.read_float()}")
52 | print(f"South: {reader.read_float()}")
53 | print(reader.read_cs_string())
54 | except:
55 | pass
56 |
57 | size = reader.tell()
58 | reader.seek(0)
59 | data = reader.read(size)
60 | with open("output.tr2", "wb") as f:
61 | f.write(data)
62 |
63 |
64 | if __name__ == "__main__":
65 | parser = argparse.ArgumentParser(description="Convert TR4 to TR2")
66 | parser.add_argument("file", help="TR2 File")
67 |
68 | args = parser.parse_args()
69 |
70 | main(args.file)
71 |
--------------------------------------------------------------------------------
/misc_scripts/updater.py:
--------------------------------------------------------------------------------
1 | import hashlib
2 | import os
3 |
4 | import requests
5 |
6 | URL = "http://www.run8-services.com/v3autoupdater/v3autoupdate.php"
7 | FILE_DOWNLOAD_URL = "http://www.run8-services.com/v3autoupdater/v3autoupdate_dl.php"
8 | BASE_PATH = "D:\\Programs\\Run8Studios\\Run8 Train Simulator V3"
9 | OUTDATED_LIST = []
10 | FILES: dict[str, str] = {}
11 |
12 |
13 | def smethod_5(dirname: str):
14 | return (
15 | "V3Routes" in dirname
16 | and not "VegTextures" in dirname
17 | and not "TrackTextures" in dirname
18 | and not "TerrainTextures" in dirname
19 | and not "Splendid Assets" in dirname
20 | and not "Regions" in dirname
21 | )
22 |
23 |
24 | def compute_file_hash(path: str):
25 | with open(path, "rb") as f:
26 | return hashlib.md5(f.read()).hexdigest().lower()
27 |
28 |
29 | def check_files():
30 | OUTDATED_LIST.clear()
31 |
32 | for file in FILES.keys():
33 | rpath = file
34 | hash_ = FILES[file]
35 |
36 | apath = BASE_PATH + rpath
37 | dirname = os.path.dirname(apath)
38 |
39 | if os.path.exists(dirname) and (not smethod_5(dirname) or os.path.exists(dirname + "/TrackDatabase.r8")):
40 | if os.path.exists(apath):
41 | file_hash = compute_file_hash(apath)
42 | if file_hash != hash_.lower():
43 | OUTDATED_LIST.append(rpath)
44 | else:
45 | OUTDATED_LIST.append(rpath)
46 |
47 |
48 | def download_file(name: str):
49 | try:
50 | r = requests.post(FILE_DOWNLOAD_URL, data={"xyz": "123", "filename": name})
51 |
52 | if r.ok:
53 | apath = BASE_PATH + name
54 | with open(apath, "wb") as f:
55 | f.write(r.content)
56 | except Exception as e:
57 | print(e)
58 |
59 |
60 | def main():
61 | print("Fetching manifest...")
62 | data = {"xyz": "123"}
63 | r = requests.post(URL, data=data)
64 |
65 | if r.ok:
66 | for text in list(filter(None, r.text.split("jwg96main"))):
67 | k, v = list(filter(None, text.split(";")))
68 | FILES[k] = v
69 |
70 | print("Checking local files against manifest...")
71 | check_files()
72 |
73 | print(f"{len(OUTDATED_LIST)} outdated files")
74 |
75 | if len(OUTDATED_LIST) == 0:
76 | print("Already up to date")
77 | exit(0)
78 |
79 | for file in OUTDATED_LIST:
80 | print(f"Downloading file: {file} ({OUTDATED_LIST.index(file) + 1}/{len(OUTDATED_LIST)})")
81 |
82 | download_file(file)
83 |
84 | print("Checking for errors...")
85 | check_files()
86 |
87 | if len(OUTDATED_LIST) > 0:
88 | print(f"Update failure! {len(OUTDATED_LIST)} files failed to verify")
89 | else:
90 | print("Update complete")
91 | else:
92 | print("Failed to get manifest.")
93 |
94 |
95 | if __name__ == "__main__":
96 | main()
97 |
--------------------------------------------------------------------------------