1
0
Fork 0
forked from len0rd/rockbox
foxbox/apps/plugins/xrick/system/sysvid_rockbox.c
Solomon Peachy eacb4daa2d More xrick-related cleanups
* 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
2024-06-30 20:30:49 -04:00

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 */