text: /*
   * PSP Software Development Kit - http://www.psvdev.org
   * -----------------------------------------------------------------------
   * Licensed under the BSD license, see LICENSE in PSPSDK root for details.
   *
   * scr_printf.c - Debug screen functions.
   *
   * Copyright (c) 2005 Marcus R. Brown <mrbrown@ocgnet.org>
   * Copyright (c) 2005 James Forshaw <tyranid@gmail.com>
   * Copyright (c) 2005 John Kelley <ps2dev@kelley.ca>
   *
   * $Id: scr_printf.c 2450 2009-01-04 23:53:02Z oopo $
   */
  #include <vitasdk.h>
  #include <stdio.h>
  #include <stdarg.h>
  #include <string.h>
  
  #include "pspdebug.h"
  
  #define PSV_SCREEN_WIDTH 960
  #define PSV_SCREEN_HEIGHT 544
  #define PSV_LINE_SIZE 960
  
  /* baseado nas libs do Duke... */
  
  void  _psvDebugScreenClearLine( int Y);
  
  static int X = 0, Y = 0;
  static int MX=68, MY=34;
  static uint32_t bg_col = 0, fg_col = 0xFFFFFFFF;
  static int bg_enable = 1;
  static void* g_vram_base = NULL;
  static int g_vram_offset = 0;
  static int g_vram_mode = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8;
  static int init = 0;
  static int clearline_en = 1;
  
  static void clear_screen_32(uint32_t color)
  {
    int x;
    uint32_t *vram = g_vram_base;
    vram +=  (g_vram_offset>>2);
  
    for(x = 0; x < (PSV_LINE_SIZE * PSV_SCREEN_HEIGHT); x++)
    {
      *vram++ = color; 
    }
  }
  
  static void clear_screen(uint32_t color)
  {
    if(g_vram_mode == SCE_DISPLAY_PIXELFORMAT_A8B8G8R8)
    {
      clear_screen_32(color);
    }
  }
  
  #define ALIGN(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
  
  void psvDebugScreenInitEx(void *vram_base, int mode, int setup)
  {
    switch(mode)
    {
      case SCE_DISPLAY_PIXELFORMAT_A8B8G8R8:
        break;
      default: mode = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8;
    };
  
    X = Y = 0;
    /* Place vram in uncached memory */
    if(vram_base == NULL)
    {
      int block = sceKernelAllocMemBlock("", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, ALIGN(PSV_LINE_SIZE * PSV_SCREEN_HEIGHT * 4, 256 * 1024), NULL);
      sceKernelGetMemBlockBase(block, &vram_base);
    }
    g_vram_base = vram_base;
    g_vram_offset = 0;
    g_vram_mode = mode;
    if(setup)
    {
      SceDisplayFrameBuf framebuf;
      framebuf.size = sizeof(SceDisplayFrameBuf);
      framebuf.base = (void *)g_vram_base;
      framebuf.pitch = PSV_LINE_SIZE;
      framebuf.width = PSV_SCREEN_WIDTH;
      framebuf.height = PSV_SCREEN_HEIGHT;
      framebuf.pixelformat = mode;
      sceDisplaySetFrameBuf(&framebuf, 1);
    }
    clear_screen(bg_col);
    init = 1;
  }
  
  void psvDebugScreenInit()
  {
    X = Y = 0;
    psvDebugScreenInitEx(NULL, SCE_DISPLAY_PIXELFORMAT_A8B8G8R8, 1);
  }
  
  void psvDebugScreenEnableBackColor(int enable) 
  {
    bg_enable = enable;
  }
  
  void psvDebugScreenSetBackColor(uint32_t colour)
  {
    bg_col = colour;
  }
  
  void psvDebugScreenSetTextColor(uint32_t colour)
  {
    fg_col = colour;
  }
  
  void psvDebugScreenSetColorMode(int mode)
  {
    switch(mode)
    {
      case SCE_DISPLAY_PIXELFORMAT_A8B8G8R8:
        break;
      default: mode = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8;
    };
  
    g_vram_mode = mode;
  }
  
  int psvDebugScreenGetX()
  {
    return X;
  }
  
  int psvDebugScreenGetY()
  {
    return Y;
  }
  
  void psvDebugScreenClear()
  {
    int y;
  
    if(!init)
    {
      return;
    }
  
    for(y=0;y<MY;y++)
    {
      _psvDebugScreenClearLine(y);
    }
  
    psvDebugScreenSetXY(0,0);
    clear_screen(bg_col);
  }
  
  void psvDebugScreenSetXY(int x, int y)
  {
    if( x<MX && x>=0 ) X=x;
    if( y<MY && y>=0 ) Y=y;
  }
  
  void psvDebugScreenSetOffset(int offset)
  {
    g_vram_offset = offset;
  }
  
  void psvDebugScreenSetBase(uint32_t* base)
  {
    g_vram_base = base;
  }
  
  extern uint8_t msx[];
  
  static void debug_put_char_32(int x, int y, uint32_t color, uint32_t bgc, uint8_t ch)
  {
    int   i,j, l;
    uint8_t  *font;
    uint32_t *vram_ptr;
    uint32_t *vram;
  
    if(!init)
    {
      return;
    }
  
    x *= 2;
    y *= 2;
  
    vram = g_vram_base;
    vram += (g_vram_offset >> 2) + x;
    vram += (y * PSV_LINE_SIZE);
  
    font = &msx[ (int)ch * 8];
    for (i=l=0; i < 8; i++, l+= 8, font++)
    {
      vram_ptr  = vram;
      for (j=0; j < 8; j++)
      {
        if ((*font & (128 >> j))) {
          vram_ptr[0] = color; 
          vram_ptr[1] = color; 
          vram_ptr[0 + PSV_LINE_SIZE] = color; 
          vram_ptr[1 + PSV_LINE_SIZE] = color; 
        } else if(bg_enable) {
          vram_ptr[0] = bgc; 
          vram_ptr[1] = bgc; 
          vram_ptr[0 + PSV_LINE_SIZE] = bgc; 
          vram_ptr[1 + PSV_LINE_SIZE] = bgc; 
        }
  
        vram_ptr += 2;
      }
      vram += 2 * PSV_LINE_SIZE;
    }
  }
  
  void
  psvDebugScreenPutChar( int x, int y, uint32_t color, uint8_t ch)
  {
    if(g_vram_mode == SCE_DISPLAY_PIXELFORMAT_A8B8G8R8)
    {
      debug_put_char_32(x, y, color, bg_col, ch);
    }
  }
  
  void  _psvDebugScreenClearLine( int Y)
  {
    if(clearline_en)
    {
      int i;
      if(bg_enable)
      {
        for (i=0; i < MX; i++)
        {
          psvDebugScreenPutChar( i*7 , Y * 8, bg_col, 219);
        }
      }
    }
    return;
  }
  
  void psvDebugScreenClearLineEnable(void)
  {
    clearline_en = 1;
    return;
  }
  
  void psvDebugScreenClearLineDisable(void)
  {
    clearline_en = 0;
    return;
  }
  
  /* Print non-nul terminated strings */
  int psvDebugScreenPrintData(const char *buff, int size)
  {
    int i;
    int j;
    char c;
  
    if(!init)
    {
      return 0;
    }
  
    for (i = 0; i < size; i++)
    {
      c = buff[i];
      switch (c)
      {
        case '\r':
              X = 0;
              break;
        case '\n':
              X = 0;
              Y ++;
              if (Y == MY)
                Y = 0;
              _psvDebugScreenClearLine(Y);
              break;
        case '\t':
              for (j = 0; j < 5; j++) {
                psvDebugScreenPutChar( X*7 , Y * 8, fg_col, ' ');
                X++;
              }
              break;
        default:
              psvDebugScreenPutChar( X*7 , Y * 8, fg_col, c);
              X++;
              if (X == MX)
              {
                X = 0;
                Y++;
                if (Y == MY)
                  Y = 0;
                _psvDebugScreenClearLine(Y);
              }
      }
    }
  
    return i;
  }
  
  int psvDebugScreenPuts(const char *str)
  {
    return psvDebugScreenPrintData(str, sceClibStrnlen(str, 2048));
  }
  
  void psvDebugScreenPrintf(const char *format, ...)
  {
    va_list  opt;
    char     buff[2048];
    int    bufsz;
  
    va_start(opt, format);
    bufsz = sceClibVsnprintf( buff, (size_t) sizeof(buff), format, opt);
    (void) psvDebugScreenPrintData(buff, bufsz);
  }
  