Flicker problem driving me crazy!

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Bluddy
Posts: 11
Joined: Sun Apr 22, 2007 9:37 pm

Flicker problem driving me crazy!

Post by Bluddy »

I'm dealing with what has to be one of the most annoying, stubborn bugs I've ever had. Every time I think I got it, it goes away and then comes back later. I'm going over everything with a fine-tooth comb and I just can't get to the root of the problem.

The problem is that I get BAD flicker, but only sometimes. In fact, I can get to a situation where I'll link, get no flicker, then I'll add a couple of C++ instructions, compile, link, and get flicker.

Here's the relevant code. I'm posting everything related to graphics since I'm really getting desperate with this bug.

Code: Select all

#define PIXEL_SIZE (4)
#define BUF_WIDTH (512)
#define   PSP_SCREEN_WIDTH   480
#define   PSP_SCREEN_HEIGHT   272
#define PSP_FRAME_SIZE (BUF_WIDTH * PSP_SCREEN_HEIGHT * PIXEL_SIZE)
#define MOUSE_SIZE   128
#define   KBD_DATA_SIZE   130560

#define   MAX_FPS   30

unsigned int __attribute__((aligned(16))) displayList[2048];
unsigned short __attribute__((aligned(16))) clut256[256];
unsigned short __attribute__((aligned(16))) mouseClut[256];
unsigned short __attribute__((aligned(16))) cursorPalette[256];
unsigned int __attribute__((aligned(16))) mouseBuf256[MOUSE_SIZE*MOUSE_SIZE];


unsigned long RGBToColour(unsigned long r, unsigned long g, unsigned long b) {
   return &#40;&#40;&#40;b >> 3&#41; << 10&#41; | &#40;&#40;g >> 3&#41; << 5&#41; | &#40;&#40;r >> 3&#41; << 0&#41;&#41; | 0x8000;
&#125;

const OSystem&#58;&#58;GraphicsMode OSystem_PSP&#58;&#58;s_supportedGraphicsModes&#91;&#93; = &#123;
   &#123; "320x200 &#40;centered&#41;", "320x200 16-bit centered", CENTERED_320X200 &#125;,
   &#123; "435x272 &#40;best-fit, centered&#41;", "435x272 16-bit centered", CENTERED_435X272 &#125;,
   &#123; "480x272 &#40;full screen&#41;", "480x272 16-bit stretched", STRETCHED_480X272 &#125;,
   &#123; "362x272 &#40;4&#58;3, centered&#41;", "362x272 16-bit centered", CENTERED_362X272 &#125;,
   &#123;0, 0, 0&#125;
&#125;;


OSystem_PSP&#58;&#58;OSystem_PSP&#40;&#41; &#58; _screenWidth&#40;0&#41;, _screenHeight&#40;0&#41;, _overlayWidth&#40;0&#41;, _overlayHeight&#40;0&#41;,
      _offscreen&#40;0&#41;, _overlayBuffer&#40;0&#41;, _overlayVisible&#40;false&#41;, _shakePos&#40;0&#41;, _lastScreenUpdate&#40;0&#41;,
      _mouseBuf&#40;0&#41;, _prevButtons&#40;0&#41;, _lastPadCheck&#40;0&#41;, _padAccel&#40;0&#41;, _mixer&#40;0&#41; &#123;
   memset&#40;_palette, 0, sizeof&#40;_palette&#41;&#41;;

   _cursorPaletteDisabled = true;

   _samplesPerSec = 0;

   //init SDL
   uint32   sdlFlags = SDL_INIT_AUDIO | SDL_INIT_TIMER;
   SDL_Init&#40;sdlFlags&#41;;

   _keyboardVisible = false;
   _clut = clut256;
   _mouseBuf = &#40;byte *&#41;mouseBuf256;
   _graphicMode = STRETCHED_480X272;
   _keySelected = 1;

   _mouseX = PSP_SCREEN_WIDTH >> 1;   // Mouse in the middle of the screen
   _mouseY = PSP_SCREEN_HEIGHT >> 1;


   // Init GU
   sceGuInit&#40;&#41;;
   sceGuStart&#40;0, displayList&#41;;
   sceGuDrawBuffer&#40;GU_PSM_8888, &#40;void *&#41;0, BUF_WIDTH&#41;;
   sceGuDispBuffer&#40;PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, &#40;void*&#41;PSP_FRAME_SIZE, BUF_WIDTH&#41;;
   sceGuDepthBuffer&#40;&#40;void*&#41;&#40;PSP_FRAME_SIZE * 2&#41;, BUF_WIDTH&#41;;
   sceGuOffset&#40;2048 - &#40;PSP_SCREEN_WIDTH/2&#41;, 2048 - &#40;PSP_SCREEN_HEIGHT/2&#41;&#41;;
   sceGuViewport&#40;2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT&#41;;
   sceGuDepthRange&#40;0xC350, 0x2710&#41;;
   sceGuScissor&#40;0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT&#41;;
   sceGuEnable&#40;GU_SCISSOR_TEST&#41;;
   sceGuFrontFace&#40;GU_CW&#41;;
   sceGuEnable&#40;GU_TEXTURE_2D&#41;;
   sceGuClear&#40;GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT&#41;;
   sceGuFinish&#40;&#41;;
   sceGuSync&#40;0,0&#41;;

   sceDisplayWaitVblankStart&#40;&#41;;
   sceGuDisplay&#40;1&#41;;

&#125;

OSystem_PSP&#58;&#58;~OSystem_PSP&#40;&#41; &#123;

   free&#40;_offscreen&#41;;
   free&#40;_overlayBuffer&#41;;
   free&#40;_mouseBuf&#41;;
   delete _keyboard;

   _offscreen = 0;
   _overlayBuffer = 0;
   _mouseBuf = 0;
    sceGuTerm&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;initSize&#40;uint width, uint height, const Graphics&#58;&#58;PixelFormat *format&#41; &#123;
   PSPDebugTrace&#40;"initSize\n"&#41;;

   _screenWidth = width;
   _screenHeight = height;

   const int scrBufSize = _screenWidth * _screenHeight * &#40;format ? format->bytesPerPixel &#58; 4&#41;;

   _overlayWidth = PSP_SCREEN_WIDTH;   //width;
   _overlayHeight = PSP_SCREEN_HEIGHT;   //height;

   free&#40;_overlayBuffer&#41;;
   _overlayBuffer = &#40;OverlayColor *&#41;memalign&#40;64, _overlayWidth * _overlayHeight * sizeof&#40;OverlayColor&#41;&#41;;
   fprintf&#40;stderr, "_overlaybuffer is from %p, size = %x\n", _overlayBuffer, _overlayWidth * _overlayHeight * sizeof&#40;OverlayColor&#41;&#41;;

   free&#40;_offscreen&#41;;
   _offscreen = &#40;byte *&#41;memalign&#40;64, scrBufSize&#41;;
   fprintf&#40;stderr, "_offscreen is at %p, size = %x\n", _offscreen, scrBufSize&#41;;
   bzero&#40;_offscreen, scrBufSize&#41;;
   
   clearOverlay&#40;&#41;;
   memset&#40;_palette, 0xFFFF, 256 * sizeof&#40;unsigned short&#41;&#41;;

   _mouseVisible = false;
   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

int16 OSystem_PSP&#58;&#58;getWidth&#40;&#41; &#123;
   return _screenWidth;
&#125;

int16 OSystem_PSP&#58;&#58;getHeight&#40;&#41; &#123;
   return _screenHeight;
&#125;

void OSystem_PSP&#58;&#58;setPalette&#40;const byte *colors, uint start, uint num&#41; &#123;
   const byte *b = colors;

   for &#40;uint i = 0; i < num; ++i&#41; &#123;
      _palette&#91;start + i&#93; = RGBToColour&#40;b&#91;0&#93;, b&#91;1&#93;, b&#91;2&#93;&#41;;
      b += 4;
   &#125;

   //copy to CLUT
   memcpy&#40;_clut, _palette, 256 * sizeof&#40;unsigned short&#41;&#41;;

   //force update of mouse CLUT as well, as it may have been set up before this palette was set
   memcpy&#40;mouseClut, _palette, 256 * sizeof&#40;unsigned short&#41;&#41;;
   mouseClut&#91;_mouseKeyColour&#93; = 0;

   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;setCursorPalette&#40;const byte *colors, uint start, uint num&#41; &#123;
   const byte *b = colors;

   for &#40;uint i = 0; i < num; ++i&#41; &#123;
      cursorPalette&#91;start + i&#93; = RGBToColour&#40;b&#91;0&#93;, b&#91;1&#93;, b&#91;2&#93;&#41;;
      b += 4;
   &#125;

   cursorPalette&#91;0&#93; = 0;

   _cursorPaletteDisabled = false;

   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;copyRectToScreen&#40;const byte *buf, int pitch, int x, int y, int w, int h&#41; &#123;
   //Clip the coordinates
   if &#40;x < 0&#41; &#123;
      w += x;
      buf -= x;
      x = 0;
   &#125;

   if &#40;y < 0&#41; &#123;
      h += y;
      buf -= y * pitch;
      y = 0;
   &#125;

   if &#40;w > _screenWidth - x&#41; &#123;
      w = _screenWidth - x;
   &#125;

   if &#40;h > _screenHeight - y&#41; &#123;
      h = _screenHeight - y;
   &#125;

   if &#40;w <= 0 || h <= 0&#41;
      return;


   byte *dst = _offscreen + y * _screenWidth + x;

   if &#40;_screenWidth == pitch && pitch == w&#41; &#123;
      memcpy&#40;dst, buf, h * w&#41;;
   &#125; else &#123;
      do &#123;
         memcpy&#40;dst, buf, w&#41;;
         buf += pitch;
         dst += _screenWidth;
      &#125; while &#40;--h&#41;;
   &#125;
   sceKernelDcacheWritebackAll&#40;&#41;;

&#125;

Graphics&#58;&#58;Surface *OSystem_PSP&#58;&#58;lockScreen&#40;&#41; &#123;
   _framebuffer.pixels = _offscreen;
   _framebuffer.w = _screenWidth;
   _framebuffer.h = _screenHeight;
   _framebuffer.pitch = _screenWidth;
   _framebuffer.bytesPerPixel = 1;

   return &_framebuffer;
&#125;

void OSystem_PSP&#58;&#58;unlockScreen&#40;&#41; &#123;
   // The screen is always completely update anyway, so we don't have to force a full update here.
   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;updateScreen&#40;&#41; &#123;
   u32 now = getMillis&#40;&#41;;
   if &#40;now - _lastScreenUpdate < 1000 / MAX_FPS&#41;
      return;

   _lastScreenUpdate = now;

   sceGuStart&#40;0, displayList&#41;;

   sceGuClearColor&#40;0xFF000000&#41;;
   sceGuClear&#40;GU_COLOR_BUFFER_BIT&#41;;

   sceGuClutMode&#40;GU_PSM_5551, 0, 0xFF, 0&#41;;
   sceGuClutLoad&#40;32, clut256&#41;; // upload 32*8 entries &#40;256&#41;
   sceGuTexMode&#40;GU_PSM_T8, 0, 0, 0&#41;; // 8-bit image
   if &#40;_screenWidth == 320&#41;
      sceGuTexImage&#40;0, 512, 256, _screenWidth, _offscreen&#41;;
   else
      sceGuTexImage&#40;0, 512, 512, _screenWidth, _offscreen&#41;;
   sceGuTexFunc&#40;GU_TFX_REPLACE, GU_TCC_RGB&#41;;
   sceGuTexFilter&#40;GU_LINEAR, GU_LINEAR&#41;;
   sceGuTexOffset&#40;0,0&#41;;
   sceGuAmbientColor&#40;0xFFFFFFFF&#41;;
   sceGuColor&#40;0xFFFFFFFF&#41;;

   Vertex *vertices = &#40;Vertex *&#41;sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
   vertices&#91;0&#93;.u = 0.5f;
   vertices&#91;0&#93;.v = 0.5f;
   vertices&#91;1&#93;.u = _screenWidth - 0.5f;
   vertices&#91;1&#93;.v = _screenHeight - 0.5f;

   switch &#40;_graphicMode&#41; &#123;
      case CENTERED_320X200&#58;
         vertices&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 320&#41; / 2;
         vertices&#91;0&#93;.y = &#40;PSP_SCREEN_HEIGHT - 200&#41; / 2;
         vertices&#91;0&#93;.z = 0;
         vertices&#91;1&#93;.x = PSP_SCREEN_WIDTH - &#40;PSP_SCREEN_WIDTH - 320&#41; / 2;
         vertices&#91;1&#93;.y = PSP_SCREEN_HEIGHT - &#40;PSP_SCREEN_HEIGHT - 200&#41; / 2;
         vertices&#91;1&#93;.z = 0;
      break;
      case CENTERED_435X272&#58;
         vertices&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 435&#41; / 2;
         vertices&#91;0&#93;.y = 0; vertices&#91;0&#93;.z = 0;
         vertices&#91;1&#93;.x = PSP_SCREEN_WIDTH - &#40;PSP_SCREEN_WIDTH - 435&#41; / 2;
         vertices&#91;1&#93;.y = PSP_SCREEN_HEIGHT;
         vertices&#91;1&#93;.z = 0;
      break;
      case STRETCHED_480X272&#58;
         vertices&#91;0&#93;.x = 0;
         vertices&#91;0&#93;.y = 0;
         vertices&#91;0&#93;.z = 0;
         vertices&#91;1&#93;.x = PSP_SCREEN_WIDTH;
         vertices&#91;1&#93;.y = PSP_SCREEN_HEIGHT;
         vertices&#91;1&#93;.z = 0;
      break;
      case CENTERED_362X272&#58;
         vertices&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 362&#41; / 2;
         vertices&#91;0&#93;.y = 0;
         vertices&#91;0&#93;.z = 0;
         vertices&#91;1&#93;.x = PSP_SCREEN_WIDTH - &#40;PSP_SCREEN_WIDTH - 362&#41; / 2;
         vertices&#91;1&#93;.y = PSP_SCREEN_HEIGHT;
         vertices&#91;1&#93;.z = 0;
      break;
   &#125;

   if &#40;_shakePos&#41; &#123;
      vertices&#91;0&#93;.y += _shakePos;
      vertices&#91;1&#93;.y += _shakePos;
   &#125;

   sceGuDrawArray&#40;GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices&#41;;
   if &#40;_screenWidth == 640&#41; &#123;
      // 2nd draw
      Vertex *vertices2 = &#40;Vertex *&#41;sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
      sceGuTexImage&#40;0, 512, 512, _screenWidth, _offscreen+512&#41;;
      vertices2&#91;0&#93;.u = 512 + 0.5f;
      vertices2&#91;0&#93;.v = vertices&#91;0&#93;.v;
      vertices2&#91;1&#93;.u = vertices&#91;1&#93;.u;
      vertices2&#91;1&#93;.v = _screenHeight - 0.5f;
      vertices2&#91;0&#93;.x = vertices&#91;0&#93;.x + &#40;vertices&#91;1&#93;.x - vertices&#91;0&#93;.x&#41; * 511 / 640;
      vertices2&#91;0&#93;.y = 0;
      vertices2&#91;0&#93;.z = 0;
      vertices2&#91;1&#93;.x = vertices&#91;1&#93;.x;
      vertices2&#91;1&#93;.y = vertices&#91;1&#93;.y;
      vertices2&#91;1&#93;.z = 0;
      sceGuDrawArray&#40;GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices2&#41;;
   &#125;


   // draw overlay
   if &#40;_overlayVisible&#41; &#123;
      Vertex *vertOverlay = &#40;Vertex *&#41;sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
      vertOverlay&#91;0&#93;.x = 0;
      vertOverlay&#91;0&#93;.y = 0;
      vertOverlay&#91;0&#93;.z = 0;
      vertOverlay&#91;1&#93;.x = PSP_SCREEN_WIDTH;
      vertOverlay&#91;1&#93;.y = PSP_SCREEN_HEIGHT;
      vertOverlay&#91;1&#93;.z = 0;
      vertOverlay&#91;0&#93;.u = 0.5f;
      vertOverlay&#91;0&#93;.v = 0.5f;
      vertOverlay&#91;1&#93;.u = _overlayWidth - 0.5f;
      vertOverlay&#91;1&#93;.v = _overlayHeight - 0.5f;
      sceGuTexMode&#40;GU_PSM_4444, 0, 0, 0&#41;; // 16-bit image
      sceGuDisable&#40;GU_ALPHA_TEST&#41;;
      sceGuEnable&#40;GU_BLEND&#41;;

      //sceGuBlendFunc&#40;GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0&#41;;
      sceGuBlendFunc&#40;GU_ADD, GU_FIX, GU_ONE_MINUS_SRC_ALPHA, 0xFFFFFFFF, 0&#41;;

      if &#40;_overlayWidth > 320&#41;
         sceGuTexImage&#40;0, 512, 512, _overlayWidth, _overlayBuffer&#41;;
      else
         sceGuTexImage&#40;0, 512, 256, _overlayWidth, _overlayBuffer&#41;;

      sceGuTexFunc&#40;GU_TFX_REPLACE, GU_TCC_RGBA&#41;;
      sceGuDrawArray&#40;GU_SPRITES,GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D,2,0,vertOverlay&#41;;
      // need to render twice for textures > 512
      if &#40; _overlayWidth > 512&#41; &#123;
         Vertex *vertOverlay2 = &#40;Vertex *&#41;sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
         sceGuTexImage&#40;0, 512, 512, _overlayWidth, _overlayBuffer + 512&#41;;
         vertOverlay2&#91;0&#93;.u = 512 + 0.5f;
         vertOverlay2&#91;0&#93;.v = vertOverlay&#91;0&#93;.v;
         vertOverlay2&#91;1&#93;.u = vertOverlay&#91;1&#93;.u;
         vertOverlay2&#91;1&#93;.v = _overlayHeight - 0.5f;
         vertOverlay2&#91;0&#93;.x = PSP_SCREEN_WIDTH * 512 / 640;
         vertOverlay2&#91;0&#93;.y = 0;
         vertOverlay2&#91;0&#93;.z = 0;
         vertOverlay2&#91;1&#93;.x = PSP_SCREEN_WIDTH;
         vertOverlay2&#91;1&#93;.y = PSP_SCREEN_HEIGHT;
         vertOverlay2&#91;1&#93;.z = 0;         
         sceGuDrawArray&#40;GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertOverlay2&#41;;
      &#125;
      sceGuDisable&#40;GU_BLEND&#41;;
   &#125;

   // draw mouse
   if &#40;_mouseVisible&#41; &#123;
      sceGuTexMode&#40;GU_PSM_T8, 0, 0, 0&#41;; // 8-bit image
      sceGuClutMode&#40;GU_PSM_5551, 0, 0xFF, 0&#41;;
      sceGuClutLoad&#40;32, _cursorPaletteDisabled ? mouseClut &#58; cursorPalette&#41;; // upload 32*8 entries &#40;256&#41;
      sceGuAlphaFunc&#40;GU_GREATER, 0, 0xFF&#41;;
      sceGuEnable&#40;GU_ALPHA_TEST&#41;;
      sceGuTexImage&#40;0, MOUSE_SIZE, MOUSE_SIZE, MOUSE_SIZE, _mouseBuf&#41;;
      sceGuTexFunc&#40;GU_TFX_MODULATE, GU_TCC_RGBA&#41;;

      Vertex *vertMouse = &#40;Vertex *&#41;sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
      vertMouse&#91;0&#93;.u = 0.5f;
      vertMouse&#91;0&#93;.v = 0.5f;
      vertMouse&#91;1&#93;.u = _mouseWidth - 0.5f;
      vertMouse&#91;1&#93;.v = _mouseHeight - 0.5f;

      //adjust cursor position
      int mX = _mouseX - _mouseHotspotX;
      int mY = _mouseY - _mouseHotspotY;

      if &#40;_overlayVisible&#41; &#123;
         float scalex, scaley;

         scalex = &#40;float&#41;PSP_SCREEN_WIDTH /_overlayWidth;
         scaley = &#40;float&#41;PSP_SCREEN_HEIGHT /_overlayHeight;

         vertMouse&#91;0&#93;.x = mX * scalex;
         vertMouse&#91;0&#93;.y = mY * scaley;
         vertMouse&#91;0&#93;.z = 0;
         vertMouse&#91;1&#93;.x = vertMouse&#91;0&#93;.x + _mouseWidth * scalex;
         vertMouse&#91;1&#93;.y = vertMouse&#91;0&#93;.y + _mouseHeight * scaley;
         vertMouse&#91;1&#93;.z = 0;
      &#125; else
         switch &#40;_graphicMode&#41; &#123;
         case CENTERED_320X200&#58;
            vertMouse&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 320&#41; / 2 + mX;
            vertMouse&#91;0&#93;.y = &#40;PSP_SCREEN_HEIGHT - 200&#41; / 2 + mY;
            vertMouse&#91;0&#93;.z = 0;
            vertMouse&#91;1&#93;.x = vertMouse&#91;0&#93;.x + _mouseWidth;
            vertMouse&#91;1&#93;.y = vertMouse&#91;0&#93;.y + _mouseHeight;
            vertMouse&#91;1&#93;.z = 0;
         break;
         case CENTERED_435X272&#58;
         &#123;
            float scalex, scaley;

            scalex = 435.0f / _screenWidth;
            scaley = 272.0f / _screenHeight;

            vertMouse&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 435&#41; / 2 + mX * scalex;
            vertMouse&#91;0&#93;.y = mY * scaley;
            vertMouse&#91;0&#93;.z = 0;
            vertMouse&#91;1&#93;.x = vertMouse&#91;0&#93;.x + _mouseWidth * scalex;
            vertMouse&#91;1&#93;.y = vertMouse&#91;0&#93;.y + _mouseHeight * scaley;
            vertMouse&#91;1&#93;.z = 0;
         &#125;
         break;
         case CENTERED_362X272&#58;
         &#123;
            float scalex, scaley;

            scalex = 362.0f / _screenWidth;
            scaley = 272.0f / _screenHeight;

            vertMouse&#91;0&#93;.x = &#40;PSP_SCREEN_WIDTH - 362&#41; / 2 + mX * scalex;
            vertMouse&#91;0&#93;.y = mY * scaley;
            vertMouse&#91;0&#93;.z = 0;
            vertMouse&#91;1&#93;.x = vertMouse&#91;0&#93;.x + _mouseWidth * scalex;
            vertMouse&#91;1&#93;.y = vertMouse&#91;0&#93;.y + _mouseHeight * scaley;
            vertMouse&#91;1&#93;.z = 0;
         &#125;
         break;
         case STRETCHED_480X272&#58;
         &#123;
            float scalex, scaley;

            scalex = &#40;float&#41;PSP_SCREEN_WIDTH / _screenWidth;
            scaley = &#40;float&#41;PSP_SCREEN_HEIGHT / _screenHeight;

            vertMouse&#91;0&#93;.x = mX * scalex;
            vertMouse&#91;0&#93;.y = mY * scaley;
            vertMouse&#91;0&#93;.z = 0;
            vertMouse&#91;1&#93;.x = vertMouse&#91;0&#93;.x + _mouseWidth * scalex;
            vertMouse&#91;1&#93;.y = vertMouse&#91;0&#93;.y + _mouseHeight * scaley;
            vertMouse&#91;1&#93;.z = 0;
         &#125;
         break;
      &#125;
      sceGuDrawArray&#40;GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertMouse&#41;;
   &#125;

   if &#40;_keyboardVisible&#41; &#123;
      _keyboard->render&#40;&#41;;
   &#125;

   sceGuFinish&#40;&#41;;
   sceGuSync&#40;0,0&#41;;

   sceDisplayWaitVblankStart&#40;&#41;;
   sceGuSwapBuffers&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;clearOverlay&#40;&#41; &#123;
   PSPDebugTrace&#40;"clearOverlay\n"&#41;;
   bzero&#40;_overlayBuffer, _overlayWidth * _overlayHeight * sizeof&#40;OverlayColor&#41;&#41;;
   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

void OSystem_PSP&#58;&#58;grabOverlay&#40;OverlayColor *buf, int pitch&#41; &#123;
   int h = _overlayHeight;
   OverlayColor *src = _overlayBuffer;

   do &#123;
      memcpy&#40;buf, src, _overlayWidth * sizeof&#40;OverlayColor&#41;&#41;;
      src += _overlayWidth;
      buf += pitch;
   &#125; while &#40;--h&#41;;
&#125;

void OSystem_PSP&#58;&#58;copyRectToOverlay&#40;const OverlayColor *buf, int pitch, int x, int y, int w, int h&#41; &#123;
   PSPDebugTrace&#40;"copyRectToOverlay\n"&#41;;

   //Clip the coordinates
   if &#40;x < 0&#41; &#123;
      w += x;
      buf -= x;
      x = 0;
   &#125;

   if &#40;y < 0&#41; &#123;
      h += y;
      buf -= y * pitch;
      y = 0;
   &#125;

   if &#40;w > _overlayWidth - x&#41; &#123;
      w = _overlayWidth - x;
   &#125;

   if &#40;h > _overlayHeight - y&#41; &#123;
      h = _overlayHeight - y;
   &#125;

   if &#40;w <= 0 || h <= 0&#41;
      return;


   OverlayColor *dst = _overlayBuffer + &#40;y * _overlayWidth + x&#41;;

   if &#40;_overlayWidth == pitch && pitch == w&#41; &#123;
      memcpy&#40;dst, buf, h * w * sizeof&#40;OverlayColor&#41;&#41;;
   &#125; else &#123;
      do &#123;
         memcpy&#40;dst, buf, w * sizeof&#40;OverlayColor&#41;&#41;;
         buf += pitch;
         dst += _overlayWidth;
      &#125; while &#40;--h&#41;;
   &#125;
   sceKernelDcacheWritebackAll&#40;&#41;;
&#125;

int16 OSystem_PSP&#58;&#58;getOverlayWidth&#40;&#41; &#123;
   return _overlayWidth;
&#125;

int16 OSystem_PSP&#58;&#58;getOverlayHeight&#40;&#41; &#123;
   return _overlayHeight;
&#125;


void OSystem_PSP&#58;&#58;grabPalette&#40;byte *colors, uint start, uint num&#41; &#123;
   uint i;
   uint16 color;

   for &#40;i = start; i < start + num; i++&#41; &#123;
      color = _palette;
      *colors++ = &#40;&#40;color & 0x1F&#41; << 3&#41;;
      *colors++ = &#40;&#40;&#40;color >> 5&#41; & 0x1F&#41; << 3&#41;;
      *colors++ = &#40;&#40;&#40;color >> 10&#41; & 0x1F&#41; << 3&#41;;
      *colors++ = &#40;color & 0x8000 ? 255 &#58; 0&#41;;
   &#125;
&#125;

void OSystem_PSP&#58;&#58;setMouseCursor&#40;const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics&#58;&#58;PixelFormat *format&#41; &#123;
   //TODO&#58; handle cursorTargetScale
   _mouseWidth = w;
   _mouseHeight = h;

   _mouseHotspotX = hotspotX;
   _mouseHotspotY = hotspotY;

   _mouseKeyColour = keycolor & 0xFF;

   memcpy&#40;mouseClut, _palette, 256 * sizeof&#40;unsigned short&#41;&#41;;
   mouseClut&#91;_mouseKeyColour&#93; = 0;

   for &#40;unsigned int i = 0; i < h; i++&#41;
      memcpy&#40;_mouseBuf + i * MOUSE_SIZE, buf + i * w, w&#41;;
      
   sceKernelDcacheWritebackAll&#40;&#41;;      
&#125;
Last edited by Bluddy on Thu Oct 22, 2009 3:38 pm, edited 2 times in total.
Bluddy
Posts: 11
Joined: Sun Apr 22, 2007 9:37 pm

Post by Bluddy »

OK I see there are no takers. Sorry for now putting the code in a proper box.

Let me add a couple of things I've figured out through my investigations: the code can run either in 320x200 mode (which is usually adjusted to be fullscreen on the PSP) or 640x480 mode (which is shrunk to fit using the GE). In 320x200 mode, I get flickering black horizontal stripes on the screen -- sometimes all the time, sometimes every few seconds, sometimes at the bottom of the screen and sometimes at other locations, though almost never at the top.

In 640x480 mode something more interesting happens: notice that we have to render twice with 512x512 pixel textures. I also get flickering here, but also, the second render (that's shifted right 512 pixels) gets the main picture but also a faint leftover of the first texture rendered! It's as if it didn't manage to write fully, perhaps because of a cache problem?

I know that the updates to the _offscreen texture (done in copyRectToScreen) are fine -- very few of them happen relatively.

Another thing I noticed is that I can make the problem go away by creating a global array. An array of char[30] will often shift *something* enough to 'fix' the problem. This is obviously very strange.

My guess is that it's some kind of cache problem, which is why moving some data helps -- we're moving to a different line in the cache. However, I went over the code several times and I can't find any specific cache problem. Adding a cache invalidate before writing the display list also didn't help.

Another guess is that it may be related to refresh issues. Perhaps for some reason I'm not really synchronized with vsync (even though I do wait for it)?

I've also tried moving the frame buffers in vram so they're not next to each other, and so they're in different locations, just in case something was creating a cache coherency problem on those specific addresses. It also doesn't help.

I'd really appreciate people's input.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Well, you could edit the post and put it in code tags. :)

Try flipping these two lines around

Code: Select all

    sceDisplayWaitVblankStart&#40;&#41;;
    sceGuSwapBuffers&#40;&#41;; 
Bluddy
Posts: 11
Joined: Sun Apr 22, 2007 9:37 pm

Post by Bluddy »

Tried swapping the lines. It didn't work, but thanks for the idea.
cory1492
Posts: 216
Joined: Fri Dec 10, 2004 1:49 pm

Post by cory1492 »

Have you tried different alignment size for your __attribute__ declarations? I see you are aligning to 64 in memalign, but only 16 in __attribute__. Not that it will actually fix the problem, though perhaps one of those is copied from in (for example) u32 but instead assembles to/winds up copying in two u16 chunks making it seem somewhat random from build to build.
Bluddy
Posts: 11
Joined: Sun Apr 22, 2007 9:37 pm

Post by Bluddy »

Cory, it used to be aligned to 16 -- I just raised it to 64 thinking it might fix the problem.

Here's some more info, courtesy of ld's mapfiles and ld scripts among others:

First of all, I can rule out the vsync idea. I tested to see what a forced vsync-less refresh looks like, and it looks nothing like the symptoms I'm experiencing and more like screen tearing.

Now, modifying the program and checking the value of the _end symbol, I find the following pattern:
08b44694 - ok
08b44914 - bad
08b44c94 - good
08b44cd4 - good
08b44d04 - good
08b44e14 - bad
08b44e54 - good
08b44e94 - good

Notice that only a value of _end with a 14 in the end seems to cause a problem. All other values are fine. In case you were wondering, the default loader script forces a 4 byte alignment on the _end symbol.

Playing around some more, I find that moving the following symbols causes the trouble:

Code: Select all

               0x0000000008b43234                finaltest
 .bss           0x0000000008b438f4       0xc0 c&#58;/pspsdk/bin/../lib/gcc/psp/4.3.3\libgcc.a&#40;unwind-dw2.o&#41;
 .bss           0x0000000008b439b4        0xc c&#58;/pspsdk/bin/../lib/gcc/psp/4.3.3\libgcc.a&#40;unwind-dw2-fde.o&#41;
 *&#40;COMMON&#41;
 COMMON         0x0000000008b439c0     0x1000 c&#58;/pspsdk/psp/lib\libc.a&#40;fdman.o&#41;
                0x0000000008b439c0                __psp_descriptormap
 COMMON         0x0000000008b449c0      0x100 c&#58;/pspsdk/psp/lib\libc.a&#40;lib_a-gdtoa-gethex.o&#41;
                0x0000000008b449c0                __hexdig
 COMMON         0x0000000008b44ac0       0x20 c&#58;/pspsdk/psp/lib\libSDL.a&#40;SDL_events.o&#41;
                0x0000000008b44ac0                SDL_ProcessEvents
 COMMON         0x0000000008b44ae0       0x24 c&#58;/pspsdk/psp/lib\libSDL.a&#40;SDL_keyboard.o&#41;
                0x0000000008b44ae0                SDL_KeyRepeat
 COMMON         0x0000000008b44b04       0x20 c&#58;/pspsdk/psp/lib\libGL.a&#40;eglMakeCurrent.o&#41;
                0x0000000008b44b04                __pspgl_context_register
 COMMON         0x0000000008b44b24      0x1f0 c&#58;/pspsdk/psp/sdk/lib\libpspgu.a&#40;guInternal.o&#41;
                0x0000000008b44b24                gu_draw_buffer
                0x0000000008b44b44                gu_object_stack
                0x0000000008b44bc4                gu_contexts
                0x0000000008b44cd8                gu_settings
                0x0000000008b44d14                . = ALIGN &#40;0x4&#41;
                0x0000000008b44d14                . = ALIGN &#40;0x4&#41;
                0x0000000008b44d14                _end = .
                0x0000000008b44d14                PROVIDE &#40;end, .&#41;
Finaltest is the array I'm using to manipulate the locations. Moving _end artificially with loader script commands doesn't seem to change anything, but changing the value of finaltest does. This seems to imply that the culprit is one of the above!

As an aside, you may notice that I have GL tagging along since SDL was built with GL support, though I'm not using SDL for graphics at all. I don't think that's an issue but if anyone thinks otherwise, please let me know.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Your problem description sounds like a cache problem. Don't you need to flush the dcache between setting the vertices and passing them to the sce functions?

Jim
Bluddy
Posts: 11
Joined: Sun Apr 22, 2007 9:37 pm

Post by Bluddy »

Your problem description sounds like a cache problem. Don't you need to flush the dcache between setting the vertices and passing them to the sce functions?

Jim
I believe that since I get the vertices from sceGuGetMemory, the addresses are in the uncached address space, so there's no need to flush. At least that's the impression I got from perusing the sceGuGetMemory code. I agree that it looks like a cache problem -- I just don't know where the problem is.
Post Reply