forked from len0rd/rockbox
* Correct broken CREDITS file causing HTML manual build failures * Fix warning on iAudio M3 and MPIO HD200 * Fix XRGB888 pixelformat builds, hopefully correctly. This should bring the board back to green. Change-Id: Ia7d54641d37db19d4cee3b5d9f5d8ab1567ac30b
409 lines
10 KiB
C
409 lines
10 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Port of xrick, a Rick Dangerous clone, to Rockbox.
|
|
* See http://www.bigorno.net/xrick/
|
|
*
|
|
* Copyright (C) 2008-2014 Pierluigi Vicinanza
|
|
*
|
|
* 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 "xrick/system/system.h"
|
|
|
|
#include "xrick/config.h"
|
|
#include "xrick/draw.h"
|
|
#include "xrick/game.h"
|
|
#include "xrick/data/img.h"
|
|
#include "xrick/debug.h"
|
|
|
|
#include "plugin.h"
|
|
#include "lib/helper.h"
|
|
|
|
/*
|
|
* Global variables
|
|
*/
|
|
U8 *sysvid_fb = NULL; /* xRick generic 320x200 8bpp frame buffer */
|
|
|
|
/*
|
|
* Local variables
|
|
*/
|
|
static fb_data palette[256] IBSS_ATTR;
|
|
static bool isVideoInitialised = false;
|
|
#ifndef HAVE_LCD_COLOR
|
|
# include "lib/grey.h"
|
|
GREY_INFO_STRUCT_IRAM
|
|
static unsigned char greybuffer[LCD_HEIGHT * LCD_WIDTH] IBSS_ATTR; /* off screen buffer */
|
|
static unsigned char *gbuf;
|
|
# if LCD_PIXELFORMAT == HORIZONTAL_PACKING
|
|
enum { GREYBUFSIZE = (((LCD_WIDTH+7)/8)*LCD_HEIGHT*16+200) };
|
|
# else
|
|
enum { GREYBUFSIZE = (LCD_WIDTH*((LCD_HEIGHT+7)/8)*16+200) };
|
|
# endif
|
|
#endif /* ndef HAVE_LCD_COLOR */
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
static fb_data *lcd_fb = NULL;
|
|
#endif
|
|
|
|
#if (LCD_HEIGHT < SYSVID_HEIGHT)
|
|
enum { ROW_RESIZE_STEP = (LCD_HEIGHT << 16) / SYSVID_HEIGHT };
|
|
|
|
static bool rowsToSkip[SYSVID_HEIGHT];
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static void calculateRowsToSkip(void)
|
|
{
|
|
U32 currentRow, prevResizedRow;
|
|
|
|
prevResizedRow = 0;
|
|
rowsToSkip[0] = false;
|
|
|
|
for (currentRow = 1; currentRow < SYSVID_HEIGHT; ++currentRow)
|
|
{
|
|
U32 resizedRow = (currentRow * ROW_RESIZE_STEP) >> 16;
|
|
if (resizedRow == prevResizedRow)
|
|
{
|
|
rowsToSkip[currentRow] = true;
|
|
}
|
|
prevResizedRow = resizedRow;
|
|
}
|
|
}
|
|
#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
|
|
|
|
#if (LCD_WIDTH < SYSVID_WIDTH)
|
|
enum { COLUMN_RESIZE_STEP = (LCD_WIDTH << 16) / (SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)) };
|
|
|
|
static bool columnsToSkip[SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)];
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static void calculateColumnsToSkip(void)
|
|
{
|
|
U32 currentColumn, prevResizedColumn;
|
|
|
|
prevResizedColumn = 0;
|
|
columnsToSkip[0] = false;
|
|
|
|
for (currentColumn = 1; currentColumn < (SYSVID_WIDTH + (DRAW_XYMAP_SCRLEFT*2)); ++currentColumn)
|
|
{
|
|
U32 resizedColumn = (currentColumn * COLUMN_RESIZE_STEP) >> 16;
|
|
if (resizedColumn == prevResizedColumn)
|
|
{
|
|
columnsToSkip[currentColumn] = true;
|
|
}
|
|
prevResizedColumn = resizedColumn;
|
|
}
|
|
}
|
|
#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void sysvid_setPalette(img_color_t *pal, U16 n)
|
|
{
|
|
U16 i;
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
#ifdef HAVE_LCD_COLOR
|
|
#if LCD_PIXELFORMAT == XRGB8888
|
|
int x = LCD_RGBPACK(pal[i].r, pal[i].g, pal[i].b);
|
|
palette[i] = FB_SCALARPACK(x);
|
|
#else
|
|
palette[i] = LCD_RGBPACK(pal[i].r, pal[i].g, pal[i].b);
|
|
#endif
|
|
#else
|
|
palette[i] = ((3 * pal[i].r) + (6 * pal[i].g) + pal[i].b) / 10;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
*
|
|
*/
|
|
void sysvid_setGamePalette()
|
|
{
|
|
sysvid_setPalette(game_colors, game_color_count);
|
|
}
|
|
|
|
/*
|
|
* Update screen
|
|
*/
|
|
void sysvid_update(const rect_t *rects)
|
|
{
|
|
unsigned sourceRow, sourceLastRow;
|
|
unsigned sourceColumn, sourceLastColumn;
|
|
unsigned resizedRow, resizedColumn;
|
|
unsigned resizedWidth, resizedHeight;
|
|
unsigned x, y;
|
|
U8 *sourceBuf, *sourceTemp;
|
|
fb_data *destBuf, *destTemp;
|
|
|
|
if (!rects)
|
|
{
|
|
return;
|
|
}
|
|
|
|
while (rects)
|
|
{
|
|
sourceRow = rects->y;
|
|
sourceLastRow = sourceRow + rects->height;
|
|
sourceColumn = rects->x;
|
|
sourceLastColumn = sourceColumn + rects->width;
|
|
|
|
#if (LCD_WIDTH < SYSVID_WIDTH)
|
|
/* skip black borders */
|
|
if (sourceColumn < -DRAW_XYMAP_SCRLEFT)
|
|
{
|
|
sourceColumn = -DRAW_XYMAP_SCRLEFT;
|
|
}
|
|
if (sourceLastColumn > (SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT))
|
|
{
|
|
sourceLastColumn = SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT;
|
|
}
|
|
|
|
/* skip unwanted columns */
|
|
while (columnsToSkip[sourceColumn + DRAW_XYMAP_SCRLEFT] /* && sourceColumn < (SYSVID_WIDTH + DRAW_XYMAP_SCRLEFT) */)
|
|
{
|
|
++sourceColumn;
|
|
}
|
|
|
|
resizedColumn = ((sourceColumn + DRAW_XYMAP_SCRLEFT) * COLUMN_RESIZE_STEP) >> 16;
|
|
resizedWidth = 0;
|
|
#else
|
|
resizedColumn = sourceColumn;
|
|
resizedWidth = rects->width;
|
|
#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
|
|
|
|
#if (LCD_HEIGHT < SYSVID_HEIGHT)
|
|
/* skip unwanted rows */
|
|
while (rowsToSkip[sourceRow] /* && sourceRow < SYSVID_HEIGHT */)
|
|
{
|
|
++sourceRow;
|
|
}
|
|
|
|
resizedRow = (sourceRow * ROW_RESIZE_STEP) >> 16;
|
|
resizedHeight = 0;
|
|
#else
|
|
resizedRow = sourceRow;
|
|
resizedHeight = rects->height;
|
|
#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
|
|
|
|
sourceBuf = sysvid_fb;
|
|
sourceBuf += sourceColumn + sourceRow * SYSVID_WIDTH;
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
if(!lcd_fb)
|
|
{
|
|
struct viewport *vp_main = rb->lcd_set_viewport(NULL);
|
|
lcd_fb = vp_main->buffer->fb_ptr;
|
|
}
|
|
destBuf = lcd_fb;
|
|
#else
|
|
destBuf = (fb_data*) greybuffer;
|
|
#endif /* HAVE_LCD_COLOR */
|
|
destBuf += resizedColumn + resizedRow * LCD_WIDTH;
|
|
|
|
#if (LCD_WIDTH < SYSVID_WIDTH)
|
|
sourceColumn += DRAW_XYMAP_SCRLEFT;
|
|
sourceLastColumn += DRAW_XYMAP_SCRLEFT;
|
|
#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
|
|
|
|
for (y = sourceRow; y < sourceLastRow; ++y)
|
|
{
|
|
#if (LCD_HEIGHT < SYSVID_HEIGHT)
|
|
if (rowsToSkip[y])
|
|
{
|
|
sourceBuf += SYSVID_WIDTH;
|
|
continue;
|
|
}
|
|
|
|
++resizedHeight;
|
|
#endif /* (LCD_HEIGHT < SYSVID_HEIGHT) */
|
|
|
|
sourceTemp = sourceBuf;
|
|
destTemp = destBuf;
|
|
for (x = sourceColumn; x < sourceLastColumn; ++x)
|
|
{
|
|
#if (LCD_WIDTH < SYSVID_WIDTH)
|
|
if (columnsToSkip[x])
|
|
{
|
|
++sourceTemp;
|
|
continue;
|
|
}
|
|
|
|
if (y == sourceRow)
|
|
{
|
|
++resizedWidth;
|
|
}
|
|
#endif /* (LCD_WIDTH < SYSVID_WIDTH) */
|
|
|
|
*destTemp = palette[*sourceTemp];
|
|
|
|
++sourceTemp;
|
|
++destTemp;
|
|
}
|
|
|
|
sourceBuf += SYSVID_WIDTH;
|
|
destBuf += LCD_WIDTH;
|
|
}
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
IFDEBUG_VIDEO2(
|
|
for (y = resizedRow; y < resizedRow + resizedHeight; ++y)
|
|
{
|
|
destBuf = lcd_fb + resizedColumn + y * LCD_WIDTH;
|
|
*destBuf = palette[0x01];
|
|
*(destBuf + resizedWidth - 1) = palette[0x01];
|
|
}
|
|
|
|
for (x = resizedColumn; x < resizedColumn + resizedWidth; ++x)
|
|
{
|
|
destBuf = rb->lcd_fb + x + resizedRow * LCD_WIDTH;
|
|
*destBuf = palette[0x01];
|
|
*(destBuf + (resizedHeight - 1) * LCD_WIDTH) = palette[0x01];
|
|
}
|
|
);
|
|
|
|
rb->lcd_update_rect(resizedColumn, resizedRow, resizedWidth, resizedHeight);
|
|
#else
|
|
grey_ub_gray_bitmap_part(greybuffer, resizedColumn, resizedRow, LCD_WIDTH, resizedColumn, resizedRow, resizedWidth, resizedHeight);
|
|
#endif /* HAVE_LCD_COLOR */
|
|
|
|
rects = rects->next;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Clear screen
|
|
* (077C)
|
|
*/
|
|
void sysvid_clear(void)
|
|
{
|
|
rb->memset(sysvid_fb, 0, sizeof(U8) * SYSVID_WIDTH * SYSVID_HEIGHT);
|
|
}
|
|
|
|
/*
|
|
* Initialise video
|
|
*/
|
|
bool sysvid_init()
|
|
{
|
|
bool success;
|
|
|
|
if (isVideoInitialised)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
IFDEBUG_VIDEO(sys_printf("xrick/video: start\n"););
|
|
|
|
success = false;
|
|
do
|
|
{
|
|
/* allocate xRick generic frame buffer into memory */
|
|
sysvid_fb = sysmem_push(sizeof(U8) * SYSVID_WIDTH * SYSVID_HEIGHT);
|
|
if (!sysvid_fb)
|
|
{
|
|
sys_error("(video) unable to allocate frame buffer");
|
|
break;
|
|
}
|
|
|
|
#ifndef HAVE_LCD_COLOR
|
|
gbuf = sysmem_push(GREYBUFSIZE);
|
|
if (!gbuf)
|
|
{
|
|
sys_error("(video) unable to allocate buffer for greyscale functions");
|
|
break;
|
|
}
|
|
|
|
if (!grey_init(gbuf, GREYBUFSIZE, GREY_ON_COP, LCD_WIDTH, LCD_HEIGHT, NULL))
|
|
{
|
|
sys_error("(video) not enough memory to initialise greyscale functions");
|
|
break;
|
|
}
|
|
#endif /* ndef HAVE_LCD_COLOR */
|
|
|
|
success = true;
|
|
} while (false);
|
|
|
|
if (!success)
|
|
{
|
|
#ifndef HAVE_LCD_COLOR
|
|
sysmem_pop(gbuf);
|
|
#endif
|
|
sysmem_pop(sysvid_fb);
|
|
return false;
|
|
}
|
|
|
|
#if (LCD_HEIGHT < SYSVID_HEIGHT)
|
|
calculateRowsToSkip();
|
|
#endif
|
|
#if (LCD_WIDTH < SYSVID_WIDTH)
|
|
calculateColumnsToSkip();
|
|
#endif
|
|
|
|
#if LCD_DEPTH > 1
|
|
rb->lcd_set_backdrop(NULL);
|
|
#endif
|
|
/* Turn off backlight timeout */
|
|
backlight_ignore_timeout();
|
|
|
|
rb->lcd_set_foreground(LCD_WHITE);
|
|
rb->lcd_set_background(LCD_BLACK);
|
|
rb->lcd_clear_display();
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
rb->lcd_update();
|
|
#else
|
|
/* switch on greyscale overlay */
|
|
grey_show(true);
|
|
#endif /* HAVE_LCD_COLOR */
|
|
|
|
isVideoInitialised = true;
|
|
IFDEBUG_VIDEO(sys_printf("xrick/video: ready\n"););
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Shutdown video
|
|
*/
|
|
void sysvid_shutdown(void)
|
|
{
|
|
if (!isVideoInitialised)
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifndef HAVE_LCD_COLOR
|
|
grey_show(false);
|
|
grey_release();
|
|
|
|
sysmem_pop(gbuf);
|
|
#endif /* ndef HAVE_LCD_COLOR */
|
|
sysmem_pop(sysvid_fb);
|
|
|
|
/* Turn on backlight timeout (revert to settings) */
|
|
backlight_use_settings();
|
|
|
|
isVideoInitialised = false;
|
|
IFDEBUG_VIDEO(sys_printf("xrick/video: stop\n"););
|
|
}
|
|
|
|
/* eof */
|