Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the proper way to use Serum_ColorizeOrApplyRotations? #32

Closed
jsm174 opened this issue May 14, 2023 · 8 comments
Closed

What is the proper way to use Serum_ColorizeOrApplyRotations? #32

jsm174 opened this issue May 14, 2023 · 8 comments

Comments

@jsm174
Copy link
Contributor

jsm174 commented May 14, 2023

To support serum rotations, libpinmame was recently updated to call OnDisplayUpdated on every cycle regardless of if the frame actually changed or not. To know if the frame changed, p_displayData will not be null.

So the new loop for OnDisplayUpdated in VPX Standalone is like this:

if (Serum_ColorizeOrApplyRotations(pController->m_pDmdData, p_displayLayout->width, p_displayLayout->height, pController->m_dmdPalette, NULL))
   pController->m_dmdUpdate = true;

if (pController->m_dmdUpdate)
   pController->m_zedmd.RenderColoredGray6(pController->m_pDmdData, pController->m_dmdPalette, p_displayLayout->width, p_displayLayout->height);

Upon calling Serum_ColorizeOrApplyRotations, if it is a new frame, I'm assuming m_pDmdData and m_dmdPalette get changed. If it is just a rotation, I'm guessing only m_dmdPalette should be changing?

I'm seeing this strange behavior where in Scared Stiff, the Press Start is getting a weird background. In Tron, I get a flickering box to the left of the Participate In Local Tournaments.

IMG_1261.mp4
trn.mp4

Should m_pDmdData, always be the non-changed frame from libpinmame or is Serum_ColorizeOrApplyRotations smart enough to just update the palette in these situations?

@jsm174
Copy link
Contributor Author

jsm174 commented May 16, 2023

Yesterday I noticed the flicker in SS, only happens when not having 1/2 credit:

flicker_short_3.mp4

In Tron I noticed I didn't get the flicker (but I don't get the stripe) if I built standalone with GCC as opposed to Clang. Whenever I've seen weird GCC / Clang differences, it was usually because a variable wasn't initialized??

trn_gcc.mp4

Just a thought.. @mkalkbrenner

@mkalkbrenner
Copy link
Collaborator

To support serum rotations, libpinmame was recently updated to call OnDisplayUpdated on every cycle regardless of if the frame actually changed or not. To know if the frame changed, p_displayData will not be null.

This makes sense if you want to render directly on the screen using libserum.
If you want to drive ZeDMD, this is the wrong way. ZeDMD handles the rotations on its own and should only receive a new frame if it changed.

@mkalkbrenner
Copy link
Collaborator

BTW with PPUC, color rotations work perfectly well on ZeDMD. But my local copy still uses an older libpinmame checkout.

@jsm174
Copy link
Contributor Author

jsm174 commented May 19, 2023

Here are the several different versions I have tried:

bool Serum::Convert(UINT8* frame, UINT8* dstFrame, UINT8* dstPalette)
{
   if (frame)
      memcpy(m_frame, frame, m_frameSize);

   unsigned int triggerId;

   if (Serum_ColorizeOrApplyRotations(m_frame, m_width, m_height, m_palette, &triggerId)) {
      memcpy(dstFrame, m_frame, m_frameSize);
      memcpy(dstPalette, m_palette, 192);

      return true;
   }

   return false;
}

Result: Flicker. Rotations seem to have correct timing

S1.mp4
bool Serum::Convert(UINT8* frame, UINT8* dstFrame, UINT8* dstPalette)
{
   if (!frame)
      return false;
   
   memcpy(m_frame, frame, m_frameSize);

   unsigned int triggerId;

   if (!Serum_Colorize(m_frame, m_width, m_height, m_palette, m_rotations, &triggerId))
      return false;

   memcpy(dstFrame, m_frame, m_frameSize);
   memcpy(dstPalette, m_palette, 192);

   return true;
}

Result: No flicker. No Rotation.

s2.mp4
bool Serum::Convert(UINT8* frame, UINT8* dstFrame, UINT8* dstPalette)
{
   if (frame)
      memcpy(m_frame, frame, m_frameSize);

   unsigned int triggerId;

   if (Serum_Colorize(m_frame, m_width, m_height, m_palette, m_rotations, &triggerId)) {
       memcpy(dstFrame, m_frame, m_frameSize);
       memcpy(dstPalette, m_palette, 192);

       return true;
   }

   return false;
}

Result: No flicker. No Rotation.

s3.mp4
bool Serum::Convert(UINT8* frame, UINT8* dstFrame, UINT8* dstPalette)
{
   bool update = false;

   if (frame) {
       memcpy(m_frame, frame, m_frameSize);

       unsigned int triggerId;

       update = Serum_Colorize(m_frame, m_width, m_height, m_palette, m_rotations, &triggerId);
   }
   else {
       update = Serum_ApplyRotations(m_palette, m_rotations);
   }

   if (update) {
      memcpy(dstFrame, m_frame, m_frameSize);
      memcpy(dstPalette, m_palette, 192);
   }

   return update;
}

Result: No flicker. Rotation at incorrect speed

s4.mp4

@mkalkbrenner
Copy link
Collaborator

I assume, we solved that issue

@jsm174
Copy link
Contributor Author

jsm174 commented May 22, 2023

yup, fixed with

40fb09c#diff-78c29ad0d127b90fa71e2834b6ddac5f31f30df50d80c64cac80b9eab1708a19R899

Thank you @mkalkbrenner and @zesinger for the countless questions and research on this.

Below is the correct way to use this function:

bool Serum::Convert(UINT8* frame, UINT8* dstFrame, UINT8* dstPalette)
{
   if (frame)
      memcpy(m_frame, frame, m_frameSize);

   unsigned int triggerId;

   bool update = Serum_ColorizeOrApplyRotations(frame ? m_frame : NULL, m_width, m_height, m_palette, &triggerId);

   if (update) {
      memcpy(dstFrame, m_frame, m_frameSize);
      memcpy(dstPalette, m_palette, 192);
   }

   return update;
}

@zesinger
Copy link
Owner

My pleasure, I'm happy I eventually fixed that issue!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants