f373c97c90
Instead of putting "#ifdef LCD_STRIDEFORMAT" at every usage of the macro it's simpler to have config.h define LCD_STRIDEFORMAT to the default of horizontal stride when the target leaves it unspecified. Change-Id: Ib187012aad65ac678dbd837b1464a83bad722411
671 lines
18 KiB
C
671 lines
18 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Additional LCD routines not present in the rockbox core
|
|
* Scrolling functions
|
|
*
|
|
* Copyright (C) 2005 Jens Arnold
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "xlcd.h"
|
|
|
|
#if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
|
|
#endif
|
|
|
|
#if LCD_STRIDEFORMAT == VERTICAL_STRIDE
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
|
|
|
|
rb->memmove(lcd_fb, lcd_fb + LCD_HEIGHT*count, length * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(LCD_WIDTH-count, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll right */
|
|
void xlcd_scroll_right(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = (LCD_WIDTH-count)*LCD_FBHEIGHT;
|
|
|
|
rb->memmove(lcd_fb + LCD_HEIGHT*count,
|
|
lcd_fb, length * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_up(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int width, length, oldmode;
|
|
|
|
fb_data *data;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
width = LCD_WIDTH-1;
|
|
data = lcd_fb;
|
|
|
|
do {
|
|
rb->memmove(data,data + count,length * sizeof(fb_data));
|
|
data += LCD_HEIGHT;
|
|
} while(width--);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, length, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll down */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int width, length, oldmode;
|
|
|
|
fb_data *data;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
width = LCD_WIDTH-1;
|
|
data = lcd_fb;
|
|
|
|
do {
|
|
rb->memmove(data + count, data, length * sizeof(fb_data));
|
|
data += LCD_HEIGHT;
|
|
} while(width--);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
#else
|
|
|
|
#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
|
|
|
|
/* Scroll left */
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = lcd_fb;
|
|
unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data, data + blockcount, blocklen);
|
|
data += LCD_FBWIDTH;
|
|
}
|
|
while (data < data_end);
|
|
}
|
|
if (bitcount)
|
|
{
|
|
int bx, y;
|
|
unsigned char *addr = lcd_fb + blocklen;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
|
|
#endif
|
|
|
|
for (y = 0; y < LCD_HEIGHT; y++)
|
|
{
|
|
unsigned char *row_addr = addr;
|
|
unsigned data = fill;
|
|
|
|
for (bx = 0; bx < blocklen; bx++)
|
|
{
|
|
--row_addr;
|
|
data = (data >> 8) | (*row_addr << bitcount);
|
|
*row_addr = data;
|
|
}
|
|
addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(LCD_WIDTH - count, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll right */
|
|
void xlcd_scroll_right(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = lcd_fb;
|
|
unsigned char *data_end = data + LCD_FBWIDTH*LCD_HEIGHT;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data + blockcount, data, blocklen);
|
|
data += LCD_FBWIDTH;
|
|
}
|
|
while (data < data_end);
|
|
}
|
|
if (bitcount)
|
|
{
|
|
int bx, y;
|
|
unsigned char *addr = lcd_fb + blockcount;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
|
|
#endif
|
|
|
|
for (y = 0; y < LCD_HEIGHT; y++)
|
|
{
|
|
unsigned char *row_addr = addr;
|
|
unsigned data = fill;
|
|
|
|
for (bx = 0; bx < blocklen; bx++)
|
|
{
|
|
data = (data << 8) | *row_addr;
|
|
*row_addr = data >> bitcount;
|
|
row_addr++;
|
|
}
|
|
addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#else /* LCD_PIXELFORMAT vertical packed or >= 8bit / pixel */
|
|
|
|
/* Scroll left */
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
fb_data *data, *data_end;
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
data = lcd_fb;
|
|
data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
|
|
length = LCD_WIDTH - count;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data, data + count, length * sizeof(fb_data));
|
|
data += LCD_WIDTH;
|
|
}
|
|
while (data < data_end);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(length, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll right */
|
|
void xlcd_scroll_right(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
|
|
fb_data *data, *data_end;
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
data = lcd_fb;
|
|
data_end = data + LCD_WIDTH*LCD_FBHEIGHT;
|
|
length = LCD_WIDTH - count;
|
|
|
|
do
|
|
{
|
|
rb->memmove(data + count, data, length * sizeof(fb_data));
|
|
data += LCD_WIDTH;
|
|
}
|
|
while (data < data_end);
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, count, LCD_HEIGHT);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
|
|
|
|
#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) || (LCD_DEPTH >= 8)
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_up(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(lcd_fb,
|
|
lcd_fb + count * LCD_FBWIDTH,
|
|
length * LCD_FBWIDTH * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, length, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll down */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(lcd_fb + count * LCD_FBWIDTH,
|
|
lcd_fb,
|
|
length * LCD_FBWIDTH * sizeof(fb_data));
|
|
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#else /* LCD_PIXELFORMAT == VERTICAL_PACKING,
|
|
LCD_PIXELFORMAT == VERTICAL_INTERLEAVED */
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_up(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if (LCD_DEPTH == 1) \
|
|
|| (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
blockcount = count >> 3;
|
|
bitcount = count & 7;
|
|
#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
|
|
blockcount = count >> 2;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
blocklen = LCD_FBHEIGHT - blockcount;
|
|
|
|
if (blockcount)
|
|
{
|
|
rb->memmove(lcd_fb,
|
|
lcd_fb + blockcount * LCD_FBWIDTH,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#if defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
|
|
asm (
|
|
"move.l %[wide],%%d3\n" /* columns = width */
|
|
|
|
".su_cloop: \n" /* repeat for every column */
|
|
"move.l %[addr],%%a1\n" /* get start address */
|
|
"move.l %[rows],%%d2\n" /* rows = row_count */
|
|
"move.l %[bkg],%%d1 \n" /* fill with background */
|
|
|
|
".su_iloop: \n" /* repeat for all rows */
|
|
"sub.l %[wide],%%a1\n" /* address -= width */
|
|
|
|
"lsl.l #8,%%d1 \n" /* old data to 2nd byte */
|
|
"move.b (%%a1),%%d1 \n" /* combine with new data byte */
|
|
"move.l %%d1,%%d0 \n" /* keep data for next round */
|
|
"lsr.l %[cnt],%%d0 \n" /* shift right */
|
|
"move.b %%d0,(%%a1) \n" /* store data */
|
|
|
|
"subq.l #1,%%d2 \n" /* rows-- */
|
|
"bne.b .su_iloop \n"
|
|
|
|
"addq.l #1,%[addr] \n" /* start_address++ */
|
|
"subq.l #1,%%d3 \n" /* columns-- */
|
|
"bne.b .su_cloop \n"
|
|
: /* outputs */
|
|
: /* inputs */
|
|
[wide]"r"(LCD_FBWIDTH),
|
|
[rows]"r"(blocklen),
|
|
[addr]"a"(lcd_fb + blocklen * LCD_FBWIDTH),
|
|
[cnt] "d"(bitcount),
|
|
[bkg] "d"(0x55 * (~rb->lcd_get_background() & 3))
|
|
: /* clobbers */
|
|
"a1", "d0", "d1", "d2", "d3"
|
|
);
|
|
#else /* C version */
|
|
int x, by;
|
|
unsigned char *addr = lcd_fb + blocklen * LCD_FBWIDTH;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = 0x55 * (~rb->lcd_get_background() & 3);
|
|
#else
|
|
const unsigned fill = 0;
|
|
#endif
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
unsigned char *col_addr = addr++;
|
|
unsigned data = fill;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
col_addr -= LCD_FBWIDTH;
|
|
data = (data << 8) | *col_addr;
|
|
*col_addr = data >> bitcount;
|
|
}
|
|
}
|
|
#endif /* CPU, LCD_DEPTH */
|
|
|
|
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
|
|
|
#if LCD_DEPTH == 2
|
|
int x, by;
|
|
fb_data *addr = lcd_fb + blocklen * LCD_FBWIDTH;
|
|
unsigned fill, mask;
|
|
|
|
fill = patterns[rb->lcd_get_background() & 3] << 8;
|
|
mask = (0xFFu >> bitcount) << bitcount;
|
|
mask |= mask << 8;
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
fb_data *col_addr = addr++;
|
|
unsigned olddata = fill;
|
|
unsigned data;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
col_addr -= LCD_FBWIDTH;
|
|
data = *col_addr;
|
|
*col_addr = (olddata ^ ((data ^ olddata) & mask)) >> bitcount;
|
|
olddata = data << 8;
|
|
}
|
|
}
|
|
#endif /* LCD_DEPTH == 2 */
|
|
|
|
#endif /* LCD_PIXELFORMAT */
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, LCD_HEIGHT - count, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
/* Scroll up */
|
|
void xlcd_scroll_down(int count)
|
|
{
|
|
/*size_t dst_stride;*/
|
|
/*struct viewport *vp_main = NULL;*/
|
|
fb_data *lcd_fb = get_framebuffer(NULL, NULL);
|
|
|
|
int bitcount=0, oldmode;
|
|
int blockcount=0, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
{
|
|
rb->lcd_clear_display();
|
|
return;
|
|
}
|
|
|
|
#if (LCD_DEPTH == 1) \
|
|
|| (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
blockcount = count >> 3;
|
|
bitcount = count & 7;
|
|
#elif (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_PACKING)
|
|
blockcount = count >> 2;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
blocklen = LCD_FBHEIGHT - blockcount;
|
|
|
|
if (blockcount)
|
|
{
|
|
rb->memmove(lcd_fb + blockcount * LCD_FBWIDTH,
|
|
lcd_fb,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#if defined(CPU_COLDFIRE) && (LCD_DEPTH == 2)
|
|
asm (
|
|
"move.l %[wide],%%d3\n" /* columns = width */
|
|
|
|
".sd_cloop: \n" /* repeat for every column */
|
|
"move.l %[addr],%%a1\n" /* get start address */
|
|
"move.l %[rows],%%d2\n" /* rows = row_count */
|
|
"move.l %[bkg],%%d1 \n" /* fill with background */
|
|
|
|
".sd_iloop: \n" /* repeat for all rows */
|
|
"lsr.l #8,%%d1 \n" /* shift right to get residue */
|
|
"clr.l %%d0 \n"
|
|
"move.b (%%a1),%%d0 \n" /* get data byte */
|
|
"lsl.l %[cnt],%%d0 \n"
|
|
"or.l %%d0,%%d1 \n" /* combine with last residue */
|
|
"move.b %%d1,(%%a1) \n" /* store data */
|
|
|
|
"add.l %[wide],%%a1\n" /* address += width */
|
|
"subq.l #1,%%d2 \n" /* rows-- */
|
|
"bne.b .sd_iloop \n"
|
|
|
|
"lea.l (1,%[addr]),%[addr] \n" /* start_address++ */
|
|
"subq.l #1,%%d3 \n" /* columns-- */
|
|
"bne.b .sd_cloop \n"
|
|
: /* outputs */
|
|
: /* inputs */
|
|
[wide]"r"(LCD_WIDTH),
|
|
[rows]"r"(blocklen),
|
|
[addr]"a"(lcd_fb + blockcount * LCD_FBWIDTH),
|
|
[cnt] "d"(bitcount),
|
|
[bkg] "d"((0x55 * (~rb->lcd_get_background() & 3)) << bitcount)
|
|
: /* clobbers */
|
|
"a1", "d0", "d1", "d2", "d3"
|
|
);
|
|
#else /* C version */
|
|
int x, by;
|
|
unsigned char *addr = lcd_fb + blockcount * LCD_FBWIDTH;
|
|
#if LCD_DEPTH == 2
|
|
unsigned fill = (0x55 * (~rb->lcd_get_background() & 3)) << bitcount;
|
|
#else
|
|
const unsigned fill = 0;
|
|
#endif
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
unsigned char *col_addr = addr++;
|
|
unsigned data = fill;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
data = (data >> 8) | (*col_addr << bitcount);
|
|
*col_addr = data;
|
|
col_addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
#endif /* CPU, LCD_DEPTH */
|
|
|
|
#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
|
|
|
|
#if LCD_DEPTH == 2
|
|
int x, by;
|
|
fb_data *addr = lcd_fb + blockcount * LCD_FBWIDTH;
|
|
unsigned fill, mask;
|
|
|
|
fill = patterns[rb->lcd_get_background() & 3] >> (8 - bitcount);
|
|
mask = (0xFFu >> bitcount) << bitcount;
|
|
mask |= mask << 8;
|
|
|
|
for (x = 0; x < LCD_WIDTH; x++)
|
|
{
|
|
fb_data *col_addr = addr++;
|
|
unsigned olddata = fill;
|
|
unsigned data;
|
|
|
|
for (by = 0; by < blocklen; by++)
|
|
{
|
|
data = *col_addr << bitcount;
|
|
*col_addr = olddata ^ ((data ^ olddata) & mask);
|
|
olddata = data >> 8;
|
|
col_addr += LCD_FBWIDTH;
|
|
}
|
|
}
|
|
#endif /* LCD_DEPTH == 2 */
|
|
|
|
#endif /* LCD_PIXELFORMAT */
|
|
}
|
|
oldmode = rb->lcd_get_drawmode();
|
|
rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
|
|
rb->lcd_fillrect(0, 0, LCD_WIDTH, count);
|
|
rb->lcd_set_drawmode(oldmode);
|
|
}
|
|
|
|
#endif /* LCD_PIXELFORMAT, LCD_DEPTH */
|
|
#endif /* LCD_STRIDEFORMAT == VERTICAL_STRIDE */
|