@@ -198,7 +198,10 @@ void C2DEffectSA::SetRoadsignText(const std::string& text, std::uint8_t line)
198
198
if (IsValidRoadsign ())
199
199
{
200
200
if (!m_effectInterface->effect .roadsign .text )
201
+ {
201
202
m_effectInterface->effect .roadsign .text = static_cast <char *>(std::malloc (64 ));
203
+ MemSetFast (m_effectInterface->effect .roadsign .text , 0 , 64 );
204
+ }
202
205
203
206
if (!m_effectInterface->effect .roadsign .text )
204
207
return ;
@@ -207,6 +210,32 @@ void C2DEffectSA::SetRoadsignText(const std::string& text, std::uint8_t line)
207
210
}
208
211
}
209
212
213
+ RwV2d& C2DEffectSA::GetRoadsignSize ()
214
+ {
215
+ if (IsValidRoadsign ())
216
+ return m_effectInterface->effect .roadsign .size ;
217
+
218
+ static RwV2d dummySize{0 , 0 };
219
+ return dummySize;
220
+ }
221
+
222
+ RwV3d& C2DEffectSA::GetRoadsignRotation ()
223
+ {
224
+ if (IsValidRoadsign ())
225
+ return m_effectInterface->effect .roadsign .rotation ;
226
+
227
+ static RwV3d dummyRotation{0 , 0 , 0 };
228
+ return dummyRotation;
229
+ }
230
+
231
+ std::string C2DEffectSA::GetRoadsignText () const
232
+ {
233
+ if (IsValidRoadsign () && m_effectInterface->effect .roadsign .text )
234
+ return std::string (m_effectInterface->effect .roadsign .text , 64 );
235
+
236
+ return " " ;
237
+ }
238
+
210
239
void C2DEffectSA::SetEscalatorBottom (const RwV3d& bottom)
211
240
{
212
241
if (IsValidEscalator ())
@@ -231,6 +260,99 @@ void C2DEffectSA::SetEscalatorDirection(std::uint8_t direction)
231
260
m_effectInterface->effect .escalator .direction = direction;
232
261
}
233
262
263
+ RwV3d& C2DEffectSA::GetEscalatorBottom ()
264
+ {
265
+ if (IsValidEscalator ())
266
+ return m_effectInterface->effect .escalator .bottom ;
267
+
268
+ static RwV3d dummyBottom{0 , 0 , 0 };
269
+ return dummyBottom;
270
+ }
271
+
272
+ RwV3d& C2DEffectSA::GetEscalatorTop ()
273
+ {
274
+ if (IsValidEscalator ())
275
+ return m_effectInterface->effect .escalator .top ;
276
+
277
+ static RwV3d dummyTop{0 , 0 , 0 };
278
+ return dummyTop;
279
+ }
280
+
281
+ RwV3d& C2DEffectSA::GetEscalatorEnd ()
282
+ {
283
+ if (IsValidEscalator ())
284
+ return m_effectInterface->effect .escalator .end ;
285
+
286
+ static RwV3d dummyEnd{0 , 0 , 0 };
287
+ return dummyEnd;
288
+ }
289
+
290
+ RpAtomic* C2DEffectSA::Roadsign_CreateAtomic (const RwV3d& position, const RwV3d& rotation, float sizeX, float sizeY, std::uint32_t numLines, char * line1, char * line2, char * line3, char * line4, std::uint32_t numLetters, std::uint8_t palleteID)
291
+ {
292
+ // Call CCustomRoadsignMgr::CreateRoadsignAtomic
293
+ RpAtomic* atomic = ((RpAtomic*(__cdecl*)(float , float , std::int32_t , char *, char *, char *, char *, std::int32_t , std::uint8_t ))0x6FF2D0 )(sizeX, sizeY, numLines, line1, line2, line3, line4, numLetters, palleteID);
294
+ RwFrame* frame = RpAtomicGetFrame (atomic);
295
+ RwFrameSetIdentity (frame);
296
+
297
+ const RwV3d axis0{1 .0f , 0 .0f , 0 .0f }, axis1{0 .0f , 1 .0f , 0 .0f }, axis2{0 .0f , 0 .0f , 1 .0f };
298
+ RwFrameRotate (frame, &axis2, rotation.z , rwCOMBINEREPLACE);
299
+ RwFrameRotate (frame, &axis0, rotation.x , rwCOMBINEPOSTCONCAT);
300
+ RwFrameRotate (frame, &axis1, rotation.y , rwCOMBINEPOSTCONCAT);
301
+
302
+ RwFrameTranslate (frame, &position, TRANSFORM_AFTER);
303
+ RwFrameUpdateObjects (frame);
304
+
305
+ return atomic;
306
+ }
307
+
308
+ std::uint32_t C2DEffectSA::Roadsign_GetPalleteIDFromFlags (std::uint8_t flags)
309
+ {
310
+ std::uint32_t id = (flags >> 4 ) & 3 ;
311
+ return id <= 3 ? id : 0 ;
312
+ }
313
+
314
+ std::uint32_t C2DEffectSA::Roadsign_GetNumLettersFromFlags (std::uint8_t flags)
315
+ {
316
+ std::uint32_t letters = (flags >> 2 ) & 3 ;
317
+ switch (letters)
318
+ {
319
+ case 1u :
320
+ return 2 ;
321
+ case 2u :
322
+ return 4 ;
323
+ case 3u :
324
+ return 8 ;
325
+ default :
326
+ return 16 ;
327
+ }
328
+ }
329
+
330
+ std::uint32_t C2DEffectSA::Roadsign_GetNumLinesFromFlags (std::uint8_t flags)
331
+ {
332
+ std::uint32_t lines = flags & 3 ;
333
+ return (lines <= 3 && lines > 0 ) ? lines : 4 ;
334
+ }
335
+
336
+ void C2DEffectSA::Roadsign_DestroyAtomic (C2DEffectSAInterface* effect)
337
+ {
338
+ if (!effect)
339
+ return ;
340
+
341
+ t2dEffectRoadsign& roadsign = effect->effect .roadsign ;
342
+ if (roadsign.atomic )
343
+ {
344
+ RwFrame* frame = RpAtomicGetFrame (roadsign.atomic );
345
+ if (frame)
346
+ {
347
+ RpAtomicSetFrame (roadsign.atomic , nullptr );
348
+ RwFrameDestroy (frame);
349
+ }
350
+
351
+ RpAtomicDestroy (roadsign.atomic );
352
+ roadsign.atomic = nullptr ;
353
+ }
354
+ }
355
+
234
356
C2DEffectSAInterface* C2DEffectSA::CreateCopy (C2DEffectSAInterface* effect)
235
357
{
236
358
C2DEffectSAInterface* copy = new C2DEffectSAInterface ();
@@ -250,17 +372,16 @@ C2DEffectSAInterface* C2DEffectSA::CreateCopy(C2DEffectSAInterface* effect)
250
372
copy->effect .roadsign .text = static_cast <char *>(std::malloc (64 ));
251
373
if (copy->effect .roadsign .text )
252
374
{
253
- std::memset (copy->effect .roadsign .text , 0 , 64 );
254
- std::strncpy (copy->effect .roadsign .text , effect->effect .roadsign .text , 64 );
255
- }
375
+ MemSetFast (copy->effect .roadsign .text , 0 , 64 );
376
+ MemCpyFast (copy->effect .roadsign .text , effect->effect .roadsign .text , 64 );
256
377
257
- copy->effect .roadsign .atomic = RpAtomicClone (effect->effect .roadsign .atomic );
378
+ copy->effect .roadsign .atomic = Roadsign_CreateAtomic (copy->position , copy->effect .roadsign .rotation , copy->effect .roadsign .size .x , copy->effect .roadsign .size .y , Roadsign_GetNumLinesFromFlags (copy->effect .roadsign .flags ), ©->effect .roadsign .text [0 ], ©->effect .roadsign .text [16 ], ©->effect .roadsign .text [32 ], ©->effect .roadsign .text [48 ], Roadsign_GetNumLettersFromFlags (copy->effect .roadsign .flags ), Roadsign_GetPalleteIDFromFlags (copy->effect .roadsign .flags ));
379
+ }
258
380
}
259
381
260
382
return copy;
261
383
}
262
384
263
- // C2DEffect::Shutdown causes random unknown crash in ntdll.dll so we need own function
264
385
void C2DEffectSA::Shutdown (C2DEffectSAInterface* effect)
265
386
{
266
387
if (!effect)
@@ -269,25 +390,13 @@ void C2DEffectSA::Shutdown(C2DEffectSAInterface* effect)
269
390
if (effect->type == e2dEffectType::ROADSIGN)
270
391
{
271
392
t2dEffectRoadsign& roadsign = effect->effect .roadsign ;
393
+ Roadsign_DestroyAtomic (effect);
272
394
273
395
if (roadsign.text )
274
396
{
275
397
std::free (roadsign.text );
276
398
roadsign.text = nullptr ;
277
399
}
278
-
279
- if (roadsign.atomic )
280
- {
281
- RwFrame* frame = RpAtomicGetFrame (roadsign.atomic );
282
- if (frame)
283
- {
284
- RpAtomicSetFrame (roadsign.atomic , nullptr );
285
- RwFrameDestroy (frame);
286
- }
287
-
288
- RpAtomicDestroy (roadsign.atomic );
289
- roadsign.atomic = nullptr ;
290
- }
291
400
}
292
401
else if (effect->type == e2dEffectType::LIGHT)
293
402
{
0 commit comments