CEMETECH
Leading The Way To The Future
Login [Register]
Username:
Password:
Autologin:

Don't have an account? Register now to chat, post, use our tools, and much more.
Latest Headlines
Online Users
There are 140 users online: 13 members, 99 guests and 28 bots.
Members: 16aroth6, charlessprinkle, fortytwo, Fryedsoft, game_1_2345, Link, tifreak8x, trmpereira, Xeda112358.
Bots: VoilaBot (1), Spinn3r (1), MSN/Bing (1), Magpie Crawler (2), Googlebot (19), MSN/Bing (4).
RSS & Social Media
SAX
You must log in to view the SAX chat widget
Author Message
souvik1997


Guru-in-Training


Joined: 19 Apr 2010
Posts: 2870

Posted: 11 Aug 2012 03:26:15 pm    Post subject: Prizm Screenshot function

I'm writing a function to store the contents of VRAM into a 24-bit .bmp, but I have no idea why it's not working. Previously I was using the 16-bit RGB 565 bitmap header, but that produced really strange colors.

Here's the code:

Code:
#define CREATEMODE_FILE 1
#define CREATEMODE_FOLDER 5
#define READ 0
#define READ_SHARE 1
#define WRITE 2
#define READWRITE 3
#define READWRITE_SHARE 4

#define RETURN_SUCCESS 0
#define RETURN_ERROR -1

#define LCD_WIDTH 384
#define LCD_HEIGHT 216

#define file_size sizeof(bmpheader)+(LCD_WIDTH*LCD_HEIGHT*3)

unsigned short filebuffer[] = {'\\','\\','f','l','s','0','\\','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'}; 
unsigned char bmpheader[] =
   {0x42, 0x4D, 0x36, 0xCC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int TakeScreenshot(char* filename) //Copies the contents of VRAM to a 24-bit .bmp file in storage memory
{
   int fh = 0;   
   Bfile_StrToName_ncpy(filebuffer+(7), filename, strlen(filename)); //copy the filename to the filebuffer after "\\fls0\"
   Bfile_DeleteEntry(filebuffer, CREATEMODE_FILE, 0);
   color_t* VRAM = (color_t*)0xA8000000;
   int size = file_size;
   if (0 > (fh = Bfile_OpenFile_OS(filebuffer,READWRITE))) {
        if (Bfile_CreateEntry_OS(filebuffer, CREATEMODE_FILE, &size) < 0)
         return RETURN_ERROR;
   }
   if (fh >= 0)
        Bfile_CloseFile_OS(fh);
   if (0 <= (fh = Bfile_OpenFile_OS(filebuffer,READWRITE))) {
      Bfile_WriteFile_OS(fh, bmpheader, sizeof(bmpheader));
      void* scratchSpace = malloc(LCD_WIDTH*3);
      for (int x = LCD_HEIGHT-1; x >= 0; x--) //bmp files are upside down
      {
         //memcpy(scratchSpace, VRAM+(LCD_WIDTH*x), LCD_WIDTH*2); <-- produces weird colors in 16 bit mode
         
         for (int y = 0; y < LCD_WIDTH; y++) // http://stackoverflow.com/questions/2442576/how-does-one-convert-16-bit-rgb565-to-24-bit-rgb888
         {
            unsigned short color = (unsigned short*)(VRAM+(LCD_WIDTH*x+y));
            unsigned char red = (char)((color & 0xf800) >> 11);
            unsigned char green = (char)((color & 0x07e0) >> 5);
            unsigned char blue = (char)(color & 0x001f);
            *((char*)scratchSpace+3*y) = ( red * 527 + 23 ) >> 6;
            *((char*)scratchSpace+3*y+1) = ( green * 259 + 33 ) >> 6;
            *((char*)scratchSpace+3*y+2) = ( blue * 527 + 23 ) >> 6;
         }
         Bfile_WriteFile_OS(fh, scratchSpace, LCD_WIDTH*3); //write chunk to file
      }   
      free(scratchSpace);
      Bfile_CloseFile_OS(fh);
   }   
   
   return RETURN_SUCCESS;
}


Edit: Here's the complete, functioning code with Tari's assembly code.

Code:
#define CREATEMODE_FILE 1
#define CREATEMODE_FOLDER 5
#define READ 0
#define READ_SHARE 1
#define WRITE 2
#define READWRITE 3
#define READWRITE_SHARE 4
#define RETURN_SUCCESS 0
#define RETURN_ERROR -1
#define LCD_WIDTH 384
#define LCD_HEIGHT 216
#define file_size sizeof(bmpheader)+(LCD_WIDTH*LCD_HEIGHT*2)

unsigned short filebuffer[] = {'\\','\\','f','l','s','0','\\','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'}; 
unsigned char bmpheader[] =
   {0x42, 0x4D, 0x46, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

int TakeScreenshot(char* filename) //Copies the contents of VRAM to a 16-bit .bmp file in storage memory
{
   int fh = 0;   
   Bfile_StrToName_ncpy(filebuffer+(7), filename, strlen(filename)); //copy the filename to the filebuffer after "\\fls0\"
   Bfile_DeleteEntry(filebuffer, CREATEMODE_FILE, 0);
   color_t* VRAM = (color_t*)0xA8000000;
   int size = file_size;
   if (Bfile_CreateEntry_OS(filebuffer, CREATEMODE_FILE, &size) < 0)
      return RETURN_ERROR;
   if (0 <= (fh = Bfile_OpenFile_OS(filebuffer,READWRITE))) {
      Bfile_WriteFile_OS(fh, bmpheader, sizeof(bmpheader));
      void* scratchSpace = malloc(LCD_WIDTH*2);
      for (int x = LCD_HEIGHT-1; x >= 0; x--) //bmp files are upside down
      {
         memcpy_littleendian(scratchSpace, VRAM+(LCD_WIDTH*x), LCD_WIDTH*2);// <-- produces weird colors in 16 bit mode
         Bfile_WriteFile_OS(fh, scratchSpace, LCD_WIDTH*2); //write chunk to file         
      }   
      free(scratchSpace);
      Bfile_CloseFile_OS(fh);
   }      
   return RETURN_SUCCESS;
}
void memcpy_littleendian(void* dest, void* source, int length)
{
   /*unsigned char* dst = (unsigned char*)dest;
   unsigned char* src = (unsigned char*)source;   
   for (int x = 0; x < length; x+=2)
   {
      *(dst+x) = *(src+x+1);
      *(dst+x+1) = *(src+x);
   }*/
   unsigned short *s = (unsigned short *)source;
    unsigned short *d = (unsigned short *)dest;
    while (length--) {
        unsigned short c = *s++;
        __asm__("swap.b %0,%0" : "=r"(c) : "0"(c));
        *d++ = c;
    }
}


_________________
CALCnet Tournament-38%


deviantArt


Last edited by souvik1997 on 20 Aug 2012 08:26:54 pm; edited 1 time in total
Back to top
AHelper


LONG LIVE COMICTECH


Joined: 30 Jan 2011
Posts: 1685
Location: Aufhelperstan, Utopian Republic

Posted: 11 Aug 2012 03:47:08 pm    Post subject:

Remember to check your endianness. The 7305 is big endian whereas your PC is little endian. All values in the BMP format must be in little endian format. To make that work, make your own memcpy to flip the endianness when it copies and your 16 bit 56500 bmp should work.

Also, the order of Bfile calls is a bit :-\. You should do Bfile_StrToName -> Bfile_DeleteEntry -> Bfile_CreateEntry -> Bfile_OpenFile.

<edit>

To 'swap' endianness, you can use the SWAP instruction if you are using asm. Otherwise, here is the C equiv. according to Renesas:

Code:
SWAPB(long m, long n)
 /* SWAP.B Rm,Rn */
{
unsigned long temp0,temp1;
temp0 = R[m] & 0xFFFF0000;
temp1 = (R[m] & 0x000000FF) << 8;
R[n] = (R[m] & 0x0000FF00) >> 8;
R[n] = R[n] | temp1 | temp0;
PC += 2;
}

_________________
°ᴥ° Get Lucky

<BrandonW> "You don't even want to know what TI Connect does when it's just detecting your calculator...It ACTUALLY ERASES THE SWAP SECTOR on every communication attempt...EVERY SINGLE ATTEMPT...Yes, TI Connect will kill your calculator..What do I have to do to get your attention?!....Such a bloated protocol."
Back to top
souvik1997


Guru-in-Training


Joined: 19 Apr 2010
Posts: 2870

Posted: 12 Aug 2012 07:20:48 am    Post subject:

Thanks, I got it working.

Code:
#define CREATEMODE_FILE 1
#define CREATEMODE_FOLDER 5
#define READ 0
#define READ_SHARE 1
#define WRITE 2
#define READWRITE 3
#define READWRITE_SHARE 4
#define RETURN_SUCCESS 0
#define RETURN_ERROR -1
#define LCD_WIDTH 384
#define LCD_HEIGHT 216
#define file_size sizeof(bmpheader)+(LCD_WIDTH*LCD_HEIGHT*2)
unsigned short filebuffer[] = {'\\','\\','f','l','s','0','\\','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'}; 
unsigned char bmpheader[] =
   {0x42, 0x4D, 0x46, 0x88, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xD8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int TakeScreenshot(char* filename) //Copies the contents of VRAM to a 16-bit .bmp file in storage memory
{
   int fh = 0;   
   Bfile_StrToName_ncpy(filebuffer+(7), filename, strlen(filename)); //copy the filename to the filebuffer after "\\fls0\"
   Bfile_DeleteEntry(filebuffer, CREATEMODE_FILE, 0);
   color_t* VRAM = (color_t*)0xA8000000;
   int size = file_size;
   if (Bfile_CreateEntry_OS(filebuffer, CREATEMODE_FILE, &size) < 0)
      return RETURN_ERROR;
   if (0 <= (fh = Bfile_OpenFile_OS(filebuffer,READWRITE))) {
      Bfile_WriteFile_OS(fh, bmpheader, sizeof(bmpheader));
      void* scratchSpace = malloc(LCD_WIDTH*2);
      for (int x = LCD_HEIGHT-1; x >= 0; x--) //bmp files are upside down
      {
         memcpy_littleendian(scratchSpace, VRAM+(LCD_WIDTH*x), LCD_WIDTH*2);//
         Bfile_WriteFile_OS(fh, scratchSpace, LCD_WIDTH*2); //write chunk to file         
      }   
      free(scratchSpace);
      Bfile_CloseFile_OS(fh);
   }      
   return RETURN_SUCCESS;
}
void memcpy_littleendian(void* dest, void* source, int length)
{
   unsigned char* dst = (unsigned char*)dest;
   unsigned char* src = (unsigned char*)source;   
   for (int x = 0; x < length; x+=2)
   {
      *(dst+x) = *(src+x+1);
      *(dst+x+1) = *(src+x);
   }
}


Edit: Oops, I didn't see your edit. I'll try to incorporate that asm code into my memcpy function.
_________________
CALCnet Tournament-38%


deviantArt


Last edited by souvik1997 on 12 Aug 2012 11:45:00 am; edited 1 time in total
Back to top
Tari


Systems Integrator


Joined: 03 Jul 2006
Posts: 2121
Location: Always-winter, Michigan

Posted: 12 Aug 2012 10:28:07 am    Post subject:

souvik1997 wrote:
Edit: Oops, I didn't see your edit. I'll try to incorporate that asm code into my memcpy function.
Simple variant:
Code:
void *memcpy_to_le(void *dst, const void *src, size_t n) {
    unsigned short *s = (unsigned short *)src;
    unsigned short *d = (unsigned short *)dst;
    while (n--) {
        unsigned short c = *s++;
        asm("swap.b %0,%0" : "=r"(c) : "0"(r));
        *d++ = c;
    }
}
The interesting bit is really just the asm() directive.
It's entirely possible that GCC will optimize the shift+mask sequence that you'd use for endianness-flipping without machine support into the processor's primitive. I haven't tested it, but it's worth trying.
_________________


Ask questions the smart way · タリ
Back to top
AHelper


LONG LIVE COMICTECH


Joined: 30 Jan 2011
Posts: 1685
Location: Aufhelperstan, Utopian Republic

Posted: 12 Aug 2012 11:14:10 am    Post subject:

Very nice that you got it working Very Happy
_________________
°ᴥ° Get Lucky

<BrandonW> "You don't even want to know what TI Connect does when it's just detecting your calculator...It ACTUALLY ERASES THE SWAP SECTOR on every communication attempt...EVERY SINGLE ATTEMPT...Yes, TI Connect will kill your calculator..What do I have to do to get your attention?!....Such a bloated protocol."
Back to top
Tari


Systems Integrator


Joined: 03 Jul 2006
Posts: 2121
Location: Always-winter, Michigan

Posted: 12 Aug 2012 08:22:36 pm    Post subject:

Tari wrote:
The interesting bit is really just the asm() directive.
It's entirely possible that GCC will optimize the shift+mask sequence that you'd use for endianness-flipping without machine support into the processor's primitive. I haven't tested it, but it's worth trying.
I noticed these builtins while browsing the GCC documentation, which are probably slightly easier variants of what I said.
Code:
int16_t __builtin_bswap16 (int16_t x)
int32_t __builtin_bswap32 (int32_t x)
int64_t __builtin_bswap64 (int64_t x)
These flip the endianness of 16, 32 and 64-bit arguments, respectively.
_________________


Ask questions the smart way · タリ
Back to top
AHelper


LONG LIVE COMICTECH


Joined: 30 Jan 2011
Posts: 1685
Location: Aufhelperstan, Utopian Republic

Posted: 13 Aug 2012 11:00:30 pm    Post subject:

Ah, I also came across those. They produce the SWAP op code directly, so use them when possible
_________________
°ᴥ° Get Lucky

<BrandonW> "You don't even want to know what TI Connect does when it's just detecting your calculator...It ACTUALLY ERASES THE SWAP SECTOR on every communication attempt...EVERY SINGLE ATTEMPT...Yes, TI Connect will kill your calculator..What do I have to do to get your attention?!....Such a bloated protocol."
Back to top
Display posts from previous:   
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
    »
» View previous topic :: View next topic  
Page 1 of 1 » All times are GMT - 5 Hours

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© Copyright 2000-2013 Cemetech & Kerm Martian :: Page Execution Time: 0.036873 seconds.