23d9812273
struct plugin_api *rb is declared in PLUGIN_HEADER, and pointed to by __header.api the loader uses this pointer to initialize rb before calling entry_point entry_point is no longer passed a pointer to the plugin API all plugins, and pluginlib functions, are modified to refer to the global rb pluginlib functions which only served to copy the API pointer are removed git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19776 a1c6a512-1295-4272-9138-f99709370657
633 lines
20 KiB
C
633 lines
20 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"
|
|
|
|
#ifdef HAVE_LCD_BITMAP
|
|
#include "xlcd.h"
|
|
|
|
#if (LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
|
|
static const unsigned short patterns[4] = {0xFFFF, 0xFF00, 0x00FF, 0x0000};
|
|
#endif
|
|
|
|
#if (LCD_PIXELFORMAT == HORIZONTAL_PACKING) && (LCD_DEPTH < 8)
|
|
|
|
/* Scroll left */
|
|
void xlcd_scroll_left(int count)
|
|
{
|
|
int bitcount, oldmode;
|
|
int blockcount, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
return;
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = rb->lcd_framebuffer;
|
|
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 = rb->lcd_framebuffer + blocklen;
|
|
#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++)
|
|
{
|
|
--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)
|
|
{
|
|
int bitcount, oldmode;
|
|
int blockcount, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_WIDTH)
|
|
return;
|
|
|
|
#if LCD_DEPTH == 2
|
|
blockcount = count >> 2;
|
|
blocklen = LCD_FBWIDTH - blockcount;
|
|
bitcount = 2 * (count & 3);
|
|
#endif
|
|
|
|
if (blockcount)
|
|
{
|
|
unsigned char *data = rb->lcd_framebuffer;
|
|
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 = rb->lcd_framebuffer + 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)
|
|
{
|
|
fb_data *data, *data_end;
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
return;
|
|
|
|
data = rb->lcd_framebuffer;
|
|
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)
|
|
{
|
|
fb_data *data, *data_end;
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_WIDTH)
|
|
return;
|
|
|
|
data = rb->lcd_framebuffer;
|
|
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)
|
|
{
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
return;
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(rb->lcd_framebuffer,
|
|
rb->lcd_framebuffer + 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)
|
|
{
|
|
int length, oldmode;
|
|
|
|
if ((unsigned)count >= LCD_HEIGHT)
|
|
return;
|
|
|
|
length = LCD_HEIGHT - count;
|
|
|
|
rb->memmove(rb->lcd_framebuffer + count * LCD_FBWIDTH,
|
|
rb->lcd_framebuffer,
|
|
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)
|
|
{
|
|
int bitcount, oldmode;
|
|
int blockcount, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
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(rb->lcd_framebuffer,
|
|
rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
|
|
asm (
|
|
"mov #0,r4 \n" /* x = 0 */
|
|
"mova .su_shifttbl,r0 \n" /* calculate jump destination for */
|
|
"mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
|
|
"bra .su_cloop \n" /* skip table */
|
|
"add r0,%[cnt] \n"
|
|
|
|
".align 2 \n"
|
|
".su_shifttbl: \n" /* shift jump offset table */
|
|
".byte .su_shift0 - .su_shifttbl \n"
|
|
".byte .su_shift1 - .su_shifttbl \n"
|
|
".byte .su_shift2 - .su_shifttbl \n"
|
|
".byte .su_shift3 - .su_shifttbl \n"
|
|
".byte .su_shift4 - .su_shifttbl \n"
|
|
".byte .su_shift5 - .su_shifttbl \n"
|
|
".byte .su_shift6 - .su_shifttbl \n"
|
|
".byte .su_shift7 - .su_shifttbl \n"
|
|
|
|
".su_cloop: \n" /* repeat for every column */
|
|
"mov %[addr],r2 \n" /* get start address */
|
|
"mov #0,r3 \n" /* current_row = 0 */
|
|
"mov #0,r1 \n" /* fill with zero */
|
|
|
|
".su_iloop: \n" /* repeat for all rows */
|
|
"sub %[wide],r2 \n" /* address -= width */
|
|
"mov.b @r2,r0 \n" /* get data byte */
|
|
"shll8 r1 \n" /* old data to 2nd byte */
|
|
"extu.b r0,r0 \n" /* extend unsigned */
|
|
"or r1,r0 \n" /* combine old data */
|
|
"jmp @%[cnt] \n" /* jump into shift "path" */
|
|
"extu.b r0,r1 \n" /* store data for next round */
|
|
|
|
".su_shift6: \n" /* shift right by 0..7 bits */
|
|
"shll2 r0 \n"
|
|
"bra .su_shift0 \n"
|
|
"shlr8 r0 \n"
|
|
".su_shift4: \n"
|
|
"shlr2 r0 \n"
|
|
".su_shift2: \n"
|
|
"bra .su_shift0 \n"
|
|
"shlr2 r0 \n"
|
|
".su_shift7: \n"
|
|
"shlr2 r0 \n"
|
|
".su_shift5: \n"
|
|
"shlr2 r0 \n"
|
|
".su_shift3: \n"
|
|
"shlr2 r0 \n"
|
|
".su_shift1: \n"
|
|
"shlr r0 \n"
|
|
".su_shift0: \n"
|
|
|
|
"mov.b r0,@r2 \n" /* store data */
|
|
"add #1,r3 \n" /* current_row++ */
|
|
"cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
|
|
"bt .su_iloop \n"
|
|
|
|
"add #1,%[addr] \n" /* start_address++ */
|
|
"add #1,r4 \n" /* x++ */
|
|
"cmp/hi r4,%[wide] \n" /* x < width ? */
|
|
"bt .su_cloop \n"
|
|
: /* outputs */
|
|
: /* inputs */
|
|
[addr]"r"(rb->lcd_framebuffer + blocklen * LCD_FBWIDTH),
|
|
[wide]"r"(LCD_FBWIDTH),
|
|
[rows]"r"(blocklen),
|
|
[cnt] "r"(bitcount)
|
|
: /* clobbers */
|
|
"r0", "r1", "r2", "r3", "r4"
|
|
);
|
|
#elif 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 */
|
|
|
|
"clr.l %%d0 \n"
|
|
"move.b (%%a1),%%d0 \n" /* get data byte */
|
|
"lsl.l #8,%%d1 \n" /* old data to 2nd byte */
|
|
"or.l %%d1,%%d0 \n" /* combine old data */
|
|
"clr.l %%d1 \n"
|
|
"move.b %%d0,%%d1 \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"(rb->lcd_framebuffer + 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 = rb->lcd_framebuffer + 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 = rb->lcd_framebuffer + 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)
|
|
{
|
|
int bitcount, oldmode;
|
|
int blockcount, blocklen;
|
|
|
|
if ((unsigned) count >= LCD_HEIGHT)
|
|
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(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH,
|
|
rb->lcd_framebuffer,
|
|
blocklen * LCD_FBWIDTH * sizeof(fb_data));
|
|
}
|
|
if (bitcount)
|
|
{
|
|
#if LCD_PIXELFORMAT == VERTICAL_PACKING
|
|
|
|
#if (CONFIG_CPU == SH7034) && (LCD_DEPTH == 1)
|
|
asm (
|
|
"mov #0,r4 \n" /* x = 0 */
|
|
"mova .sd_shifttbl,r0 \n" /* calculate jump destination for */
|
|
"mov.b @(r0,%[cnt]),%[cnt] \n" /* shift amount from table */
|
|
"bra .sd_cloop \n" /* skip table */
|
|
"add r0,%[cnt] \n"
|
|
|
|
".align 2 \n"
|
|
".sd_shifttbl: \n" /* shift jump offset table */
|
|
".byte .sd_shift0 - .sd_shifttbl \n"
|
|
".byte .sd_shift1 - .sd_shifttbl \n"
|
|
".byte .sd_shift2 - .sd_shifttbl \n"
|
|
".byte .sd_shift3 - .sd_shifttbl \n"
|
|
".byte .sd_shift4 - .sd_shifttbl \n"
|
|
".byte .sd_shift5 - .sd_shifttbl \n"
|
|
".byte .sd_shift6 - .sd_shifttbl \n"
|
|
".byte .sd_shift7 - .sd_shifttbl \n"
|
|
|
|
".sd_cloop: \n" /* repeat for every column */
|
|
"mov %[addr],r2 \n" /* get start address */
|
|
"mov #0,r3 \n" /* current_row = 0 */
|
|
"mov #0,r1 \n" /* fill with zero */
|
|
|
|
".sd_iloop: \n" /* repeat for all rows */
|
|
"shlr8 r1 \n" /* shift right to get residue */
|
|
"mov.b @r2,r0 \n" /* get data byte */
|
|
"jmp @%[cnt] \n" /* jump into shift "path" */
|
|
"extu.b r0,r0 \n" /* extend unsigned */
|
|
|
|
".sd_shift6: \n" /* shift left by 0..7 bits */
|
|
"shll8 r0 \n"
|
|
"bra .sd_shift0 \n"
|
|
"shlr2 r0 \n"
|
|
".sd_shift4: \n"
|
|
"shll2 r0 \n"
|
|
".sd_shift2: \n"
|
|
"bra .sd_shift0 \n"
|
|
"shll2 r0 \n"
|
|
".sd_shift7: \n"
|
|
"shll2 r0 \n"
|
|
".sd_shift5: \n"
|
|
"shll2 r0 \n"
|
|
".sd_shift3: \n"
|
|
"shll2 r0 \n"
|
|
".sd_shift1: \n"
|
|
"shll r0 \n"
|
|
".sd_shift0: \n"
|
|
|
|
"or r0,r1 \n" /* combine with last residue */
|
|
"mov.b r1,@r2 \n" /* store data */
|
|
"add %[wide],r2 \n" /* address += width */
|
|
"add #1,r3 \n" /* current_row++ */
|
|
"cmp/hi r3,%[rows] \n" /* current_row < bheight - shift ? */
|
|
"bt .sd_iloop \n"
|
|
|
|
"add #1,%[addr] \n" /* start_address++ */
|
|
"add #1,r4 \n" /* x++ */
|
|
"cmp/hi r4,%[wide] \n" /* x < width ? */
|
|
"bt .sd_cloop \n"
|
|
: /* outputs */
|
|
: /* inputs */
|
|
[addr]"r"(rb->lcd_framebuffer + blockcount * LCD_FBWIDTH),
|
|
[wide]"r"(LCD_WIDTH),
|
|
[rows]"r"(blocklen),
|
|
[cnt] "r"(bitcount)
|
|
: /* clobbers */
|
|
"r0", "r1", "r2", "r3", "r4"
|
|
);
|
|
#elif 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"(rb->lcd_framebuffer + 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 = rb->lcd_framebuffer + 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 = rb->lcd_framebuffer + 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 /* HAVE_LCD_BITMAP */
|