1+ using Common ;
12using Dat . Data ;
23using Dat . FileParsing ;
34using Definitions . ObjectModels ;
@@ -14,14 +15,15 @@ public static class Constants
1415 {
1516 public const int CompatibleVehicleCount = 8 ;
1617 public const int RequiredTrackExtrasCount = 4 ;
17- public const int CarComponentsCount = 4 ;
18- public const int AnimationCount = 2 ;
19- public const int CompatibleCargoTypesLength = 2 ;
18+ public const int MaxCarComponents = 4 ;
19+ public const int MaxCompatibleCargoCategories = 2 ;
2020 public const int CargoTypeSpriteOffsetsLength = 32 ;
2121 public const int MaxUnionSoundStructLength = 0x1B ;
2222 public const int MaxBodySprites = 4 ;
2323 public const int MaxBogieSprites = 2 ;
2424 public const int MaxStartSounds = 3 ;
25+ public const int MaxSimpleAnimations = 2 ;
26+ public const int Var135PadSize = 0x15A - 0x135 ;
2527 }
2628
2729 public static class StructSizes
@@ -71,14 +73,14 @@ private static void LoadVariable(LocoBinaryReader br, VehicleObject model, byte
7173 }
7274
7375 // required track extra
74- model . RequiredTrackExtras = br . ReadS5HeaderList ( numRequiredTrackExtras ) ;
76+ model . RequiredTrackExtras = br . ReadS5HeaderList ( numRequiredTrackExtras ) . ToArray ( ) ;
7577
7678 // compatible cargo
77- for ( var i = 0 ; i < Constants . CompatibleCargoTypesLength ; ++ i )
79+ for ( var i = 0 ; i < Constants . MaxCompatibleCargoCategories ; ++ i )
7880 {
79- model . CompatibleCargoCategories . Add ( [ ] ) ;
81+ model . CompatibleCargoCategories [ i ] = [ ] ;
8082 var index = model . NumSimultaneousCargoTypes ;
81- model . MaxCargo . Add ( br . ReadByte ( ) ) ;
83+ model . MaxCargo [ index ] = br . ReadByte ( ) ;
8284
8385 if ( model . MaxCargo [ index ] == 0 )
8486 {
@@ -122,7 +124,7 @@ private static void LoadVariable(LocoBinaryReader br, VehicleObject model, byte
122124 }
123125
124126 // compatible vehicles
125- model . CompatibleVehicles = br . ReadS5HeaderList ( numCompatibleVehicles ) ;
127+ model . CompatibleVehicles = br . ReadS5HeaderList ( numCompatibleVehicles ) . ToArray ( ) ;
126128
127129 // rack rail
128130 if ( model . Flags . HasFlag ( VehicleObjectFlags . RackRail ) )
@@ -139,7 +141,7 @@ private static void LoadVariable(LocoBinaryReader br, VehicleObject model, byte
139141 // driving start sounds
140142 const int mask = 127 ;
141143 var count = numStartSounds & mask ;
142- model . StartSounds = br . ReadS5HeaderList ( count ) ;
144+ model . StartSounds = br . ReadS5HeaderList ( count ) . ToArray ( ) ;
143145 }
144146
145147 private static void LoadFixed ( LocoBinaryReader br , VehicleObject model , out byte numRequiredTrackExtras , out byte numCompatibleVehicles , out byte numStartSounds )
@@ -159,19 +161,19 @@ private static void LoadFixed(LocoBinaryReader br, VehicleObject model, out byte
159161 numCompatibleVehicles = br . ReadByte ( ) ;
160162 br . SkipUInt16 ( Constants . CompatibleVehicleCount ) ;
161163 br . SkipByte ( Constants . RequiredTrackExtrasCount ) ;
162- model . CarComponents = br . ReadCarComponents ( Constants . CarComponentsCount ) ;
164+ model . CarComponents = br . ReadCarComponents ( Constants . MaxCarComponents ) ;
163165 model . BodySprites = br . ReadBodySprites ( Constants . MaxBodySprites ) ;
164166 model . BogieSprites = br . ReadBogieSprites ( Constants . MaxBogieSprites ) ;
165167 model . Power = br . ReadUInt16 ( ) ;
166168 model . Speed = br . ReadInt16 ( ) ;
167169 model . RackSpeed = br . ReadInt16 ( ) ;
168170 model . Weight = br . ReadUInt16 ( ) ;
169171 model . Flags = ( ( DatVehicleObjectFlags ) br . ReadUInt16 ( ) ) . Convert ( ) ;
170- br . SkipByte ( Constants . CompatibleCargoTypesLength * 1 ) ; // MaxCargo, read in LoadVariable
171- br . SkipByte ( Constants . CompatibleCargoTypesLength * 4 ) ; // CompatibleCargoCategories, read in LoadVariable
172+ br . SkipByte ( Constants . MaxCompatibleCargoCategories * 1 ) ; // MaxCargo, read in LoadVariable
173+ br . SkipByte ( Constants . MaxCompatibleCargoCategories * 4 ) ; // CompatibleCargoCategories, read in LoadVariable
172174 br . SkipByte ( Constants . CargoTypeSpriteOffsetsLength * 1 ) ; // CargoTypeSpriteOffsets, read in LoadVariable
173175 br . SkipByte ( ) ; // NumSimultaneousCargoTypes, manipulated in LoadVariable
174- model . Animation = br . ReadSimpleAnimations ( Constants . AnimationCount ) ;
176+ model . Animation = br . ReadSimpleAnimations ( Constants . MaxSimpleAnimations ) ;
175177 model . ShipWakeOffset = br . ReadByte ( ) ; // the distance between each wake of the boat. 0 will be a single wake. anything > 0 gives dual wakes
176178 model . DesignedYear = br . ReadUInt16 ( ) ;
177179 model . ObsoleteYear = br . ReadUInt16 ( ) ;
@@ -216,29 +218,29 @@ public static void Save(Stream stream, LocoObject obj)
216218 bw . Write ( ( uint8_t ) model . Type . Convert ( ) ) ;
217219 bw . Write ( model . NumCarComponents ) ;
218220 bw . WriteEmptyObjectId ( ) ; // TrackTypeId, not part of object definition
219- bw . Write ( ( uint8_t ) model . RequiredTrackExtras . Count ) ;
221+ bw . Write ( ( uint8_t ) model . RequiredTrackExtras . Length ) ;
220222 bw . Write ( model . CostIndex ) ;
221223 bw . Write ( model . CostFactor ) ;
222224 bw . Write ( model . Reliability ) ;
223225 bw . Write ( model . RunCostIndex ) ;
224226 bw . Write ( model . RunCostFactor ) ;
225227 bw . Write ( ( uint8_t ) model . SpecialColourSchemeIndex . Convert ( ) ) ;
226- bw . Write ( ( uint8_t ) model . CompatibleVehicles . Count ) ;
228+ bw . Write ( ( uint8_t ) model . CompatibleVehicles . Length ) ;
227229 bw . WriteEmptyBytes ( Constants . CompatibleVehicleCount * 2 ) ;
228230 bw . WriteEmptyBytes ( Constants . RequiredTrackExtrasCount ) ;
229- bw . Write ( model . CarComponents ) ;
230- bw . Write ( model . BodySprites ) ;
231- bw . Write ( model . BogieSprites ) ;
231+ bw . Write ( model . CarComponents . Fill ( Constants . MaxCarComponents , new VehicleObjectCar ( ) ) . ToArray ( ) ) ;
232+ bw . Write ( model . BodySprites . Fill ( Constants . MaxBodySprites , new BodySprite ( ) ) . ToArray ( ) ) ;
233+ bw . Write ( model . BogieSprites . Fill ( Constants . MaxBogieSprites , new BogieSprite ( ) ) . ToArray ( ) ) ;
232234 bw . Write ( model . Power ) ;
233235 bw . Write ( model . Speed ) ;
234236 bw . Write ( model . RackSpeed ) ;
235237 bw . Write ( model . Weight ) ;
236238 bw . Write ( ( uint16_t ) model . Flags . Convert ( ) ) ;
237- bw . WriteEmptyBytes ( Constants . CompatibleCargoTypesLength * 1 ) ; // MaxCargo, read in LoadVariable
238- bw . WriteEmptyBytes ( Constants . CompatibleCargoTypesLength * 4 ) ; // CompatibleCargoCategories, read in LoadVariable
239+ bw . WriteEmptyBytes ( Constants . MaxCompatibleCargoCategories * 1 ) ; // MaxCargo, read in LoadVariable
240+ bw . WriteEmptyBytes ( Constants . MaxCompatibleCargoCategories * 4 ) ; // CompatibleCargoCategories, read in LoadVariable
239241 bw . WriteEmptyBytes ( Constants . CargoTypeSpriteOffsetsLength * 1 ) ; // CargoTypeSpriteOffsets, read in LoadVariable
240242 bw . WriteEmptyBytes ( 1 ) ; // NumSimultaneousCargoTypes, manipulated in LoadVariable
241- bw . Write ( model . Animation ) ;
243+ bw . Write ( model . Animation . Fill ( Constants . MaxSimpleAnimations , new SimpleAnimation ( ) ) . ToArray ( ) ) ;
242244 bw . Write ( model . ShipWakeOffset ) ; // the distance between each wake of the boat. 0 will be a single wake. anything > 0 gives dual wakes
243245 bw . Write ( model . DesignedYear ) ;
244246 bw . Write ( model . ObsoleteYear ) ;
@@ -270,8 +272,8 @@ public static void Save(Stream stream, LocoObject obj)
270272 throw new ArgumentOutOfRangeException ( nameof ( model . DrivingSoundType ) , model . DrivingSoundType , null ) ;
271273 }
272274
273- bw . Write ( model . var_135 ) ;
274- bw . Write ( ( uint8_t ) model . StartSounds . Count ) ;
275+ bw . Write ( model . var_135 . Fill ( Constants . Var135PadSize , ( byte ) 0 ) . ToArray ( ) ) ;
276+ bw . Write ( ( uint8_t ) model . StartSounds . Length ) ;
275277 bw . WriteEmptyBytes ( Constants . MaxStartSounds * 1 ) ; // StartSounds, not part of object
276278
277279 // sanity check
@@ -281,66 +283,70 @@ public static void Save(Stream stream, LocoObject obj)
281283 SawyerStreamWriter . WriteStringTable ( stream , obj . StringTable ) ;
282284
283285 // variable
284- {
285- // track type
286- if ( ! model . Flags . HasFlag ( VehicleObjectFlags . AnyRoadType ) && ( model . Mode == TransportMode . Rail || model . Mode == TransportMode . Road ) )
287- {
288- bw . WriteS5Header ( model . TrackType ) ;
289- }
286+ SaveVariable ( model , bw ) ;
290287
291- // track extras
292- foreach ( var x in model . RequiredTrackExtras )
293- {
294- bw . WriteS5Header ( x ) ;
295- }
288+ // image table
289+ SawyerStreamWriter . WriteImageTable ( stream , obj . GraphicsElements ) ;
290+ }
291+ }
296292
297- // cargo types
298- for ( var i = 0 ; i < Constants . CompatibleCargoTypesLength ; ++ i ) // CompatibleCargoTypesLength should == CompatibleCargoCategories.Length
299- {
300- if ( model . MaxCargo . Count < i || model . MaxCargo [ i ] == 0 )
301- {
302- bw . WriteEmptyBytes ( 1 ) ; // write a 0 for MaxCargo - this indicates no more cargo and we skip the rest
303- continue ;
304- }
305- else
306- {
307- bw . Write ( model . MaxCargo [ i ] ) ;
308- }
309-
310- foreach ( var cc in model . CompatibleCargoCategories [ i ] )
311- {
312- bw . Write ( BitConverter . GetBytes ( ( uint16_t ) cc ) ) ;
313- bw . Write ( model . CargoTypeSpriteOffsets [ cc ] ) ;
314- }
315-
316- bw . Write ( BitConverter . GetBytes ( ( uint16_t ) CargoCategory . NULL ) ) ;
317- }
293+ private static void SaveVariable ( VehicleObject model , LocoBinaryWriter bw )
294+ {
295+ // track type
296+ if ( ! model . Flags . HasFlag ( VehicleObjectFlags . AnyRoadType ) && ( model . Mode == TransportMode . Rail || model . Mode == TransportMode . Road ) )
297+ {
298+ bw . WriteS5Header ( model . TrackType ) ;
299+ }
300+
301+ // track extras
302+ foreach ( var x in model . RequiredTrackExtras )
303+ {
304+ bw . WriteS5Header ( x ) ;
305+ }
306+
307+ // cargo types
308+ for ( var i = 0 ; i < Constants . MaxCompatibleCargoCategories ; ++ i ) // CompatibleCargoTypesLength should == CompatibleCargoCategories.Length
309+ {
310+ if ( model . MaxCargo . Length < i || model . MaxCargo [ i ] == 0 )
311+ {
312+ bw . WriteEmptyBytes ( 1 ) ; // write a 0 for MaxCargo - this indicates no more cargo and we skip the rest
313+ continue ;
314+ }
315+ else
316+ {
317+ bw . Write ( model . MaxCargo [ i ] ) ;
318+ }
318319
319- // animation
320- bw . WriteS5HeaderList ( model . AnimationHeaders ) ;
320+ var compatibleCargoCategories = model . CompatibleCargoCategories . Fill ( Constants . MaxCompatibleCargoCategories , [ ] ) . ToArray ( ) ;
321+ foreach ( var cc in compatibleCargoCategories [ i ] )
322+ {
323+ bw . Write ( BitConverter . GetBytes ( ( uint16_t ) cc ) ) ;
324+ bw . Write ( model . CargoTypeSpriteOffsets [ cc ] ) ;
325+ }
321326
322- // compatible vehicles
323- bw . WriteS5HeaderList ( model . CompatibleVehicles ) ;
327+ bw . Write ( BitConverter . GetBytes ( ( uint16_t ) CargoCategory . NULL ) ) ;
328+ }
324329
325- // rack rail
326- if ( model . Flags . HasFlag ( VehicleObjectFlags . RackRail ) )
327- {
328- bw . WriteS5Header ( model . RackRail ) ;
329- }
330+ // animation
331+ bw . WriteS5HeaderList ( model . AnimationHeaders ) ;
330332
331- // driving sound
332- if ( model . DrivingSoundType != DrivingSoundType . None )
333- {
334- bw . WriteS5Header ( model . Sound ) ;
335- }
333+ // compatible vehicles
334+ bw . WriteS5HeaderList ( model . CompatibleVehicles ) ;
336335
337- // driving start sounds
338- bw . WriteS5HeaderList ( model . StartSounds ) ;
339- }
336+ // rack rail
337+ if ( model . Flags . HasFlag ( VehicleObjectFlags . RackRail ) )
338+ {
339+ bw . WriteS5Header ( model . RackRail ) ;
340+ }
340341
341- // image table
342- SawyerStreamWriter . WriteImageTable ( stream , obj . GraphicsElements ) ;
342+ // driving sound
343+ if ( model . DrivingSoundType != DrivingSoundType . None )
344+ {
345+ bw . WriteS5Header ( model . Sound ) ;
343346 }
347+
348+ // driving start sounds
349+ bw . WriteS5HeaderList ( model . StartSounds ) ;
344350 }
345351}
346352
0 commit comments