cSDL/src/video/prizm/SDL_prizmvideo.c

258 lines
7.3 KiB
C

/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2012 Sam Lantinga
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL.h"
#include "SDL_config.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "SDL_prizmvideo.h"
#include "SDL_prizmevents_c.h"
#include <gint/gint.h>
#include <gint/display.h>
//#include "SDL_tinspireevents_c.h"
static Uint16 prz_palette[256] = {0};
/* Initialization/Query functions */
static int PRZ_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Rect **PRZ_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
static SDL_Surface *PRZ_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int PRZ_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);
static void PRZ_VideoQuit(_THIS);
/* etc. */
static void PRZ_UpdateRects(_THIS, int numrects, SDL_Rect *rects);
/* NSP driver bootstrap functions */
static int PRZ_Available(void)
{
return(1);
}
static void PRZ_DeleteDevice(SDL_VideoDevice *device)
{
SDL_free(device->hidden);
SDL_free(device);
}
static SDL_VideoDevice *PRZ_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
if ( device ) {
SDL_memset(device, 0, (sizeof *device));
device->hidden = (struct SDL_PrivateVideoData *)
SDL_malloc((sizeof *device->hidden));
}
if ( (device == NULL) || (device->hidden == NULL) ) {
SDL_OutOfMemory();
if ( device ) {
SDL_free(device);
}
return(0);
}
SDL_memset(device->hidden, 0, (sizeof *device->hidden));
/* Set the function pointers */
device->VideoInit = PRZ_VideoInit;
device->ListModes = PRZ_ListModes;
device->SetVideoMode = PRZ_SetVideoMode;
device->SetColors = PRZ_SetColors;
device->UpdateRects = PRZ_UpdateRects;
device->VideoQuit = PRZ_VideoQuit;
device->InitOSKeymap = PRZ_InitOSKeymap;
device->PumpEvents = PRZ_PumpEvents;
device->free = PRZ_DeleteDevice;
return device;
}
VideoBootStrap PRZ_bootstrap = {
"prizm", "SDL Casio PRIZM video driver",
PRZ_Available, PRZ_CreateDevice
};
static int PRZ_VideoInit(_THIS, SDL_PixelFormat *vformat)
{
this->hidden->cx = (int) true;
this->info.current_w = DWIDTH;
this->info.current_h = DHEIGHT;
if ( this->hidden->cx ) {
vformat->BitsPerPixel = 16;
vformat->Rmask = PRZ_RMASK16;
vformat->Gmask = PRZ_GMASK16;
vformat->Bmask = PRZ_BMASK16;
}
return(0);
}
static SDL_Rect **PRZ_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
{
return (SDL_Rect **) -1;
}
static SDL_Surface *PRZ_SetVideoMode(_THIS, SDL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
Uint32 rmask, gmask, bmask;
//NSP_DEBUG("Initializing display (%dx%dx%d)", width, height, bpp);
//if ( flags != SDL_SWSURFACE )
// NSP_WARNING("Initializing with non-typical flags");
if ( width < DWIDTH || height < DHEIGHT ) {
int win_x = (DWIDTH - width) / 2;
int win_y = (DHEIGHT - height) / 2;
this->hidden->offset = (int)PRZ_PIXEL_ADDR(0, win_x, win_y, 2 * DWIDTH, 2);
this->hidden->win_x = win_x;
} else
this->hidden->offset = this->hidden->win_x = 0;
if ( bpp == 16 ) {
rmask = PRZ_RMASK16;
gmask = PRZ_GMASK16;
bmask = PRZ_BMASK16;
}
if ( this->hidden->buffer ) {
SDL_free( this->hidden->buffer );
}
this->hidden->buffer2 = SDL_malloc((bpp / 8) * DWIDTH * DHEIGHT);
if ( ! this->hidden->buffer2 ) {
//SDL_SetError("Couldn't allocate buffer2 for requested mode");
return(NULL);
}
this->hidden->buffer = SDL_malloc((bpp / 8) * width * height);
if ( ! this->hidden->buffer ) {
SDL_free(this->hidden->buffer2);
//SDL_SetError("Couldn't allocate buffer for requested mode");
return(NULL);
}
memset(this->hidden->buffer2, 0, (bpp / 8) * DWIDTH * DHEIGHT);
memset(this->hidden->buffer, 0, (bpp / 8) * width * height);
/* Allocate the new pixel format for the screen */
if ( ! SDL_ReallocFormat(current, bpp, rmask, gmask, bmask, 0) ) {
SDL_free(this->hidden->buffer);
this->hidden->buffer = NULL;
//SDL_SetError("Couldn't allocate new pixel format for requested mode");
return(NULL);
}
/* Set up the new mode framebuffer */
current->flags = flags;
this->hidden->w = this->info.current_w = current->w = width;
this->hidden->h = this->info.current_h = current->h = height;
current->pitch = (bpp / 8) * current->w;
current->pixels = this->hidden->buffer;
//NSP_DEBUG("Done (0x%p)", current);
/* We're done */
return(current);
}
#define PRZ_DRAW_LOOP(code) do { \
while ( rows-- ) { \
j = 0, k = 0; \
code \
src_addr += src_skip; \
dst_addr += dst_skip; \
} \
} while (0)
static void PRZ_UpdateRects(_THIS, int numrects, SDL_Rect *rects)
{
int src_skip = SDL_VideoSurface->pitch;
int dst_skip = (2 * DWIDTH);
int i, j, k;
if ( this->hidden->buffer2 == NULL )
return;
for ( i = 0; i < numrects; ++i ) {
SDL_Rect *rect = &rects[i];
Uint8 *src_addr, *dst_addr;
SDL_bool odd_left, odd_right;
int row_bytes, rows;
if ( ! rect )
continue;
src_addr = PRZ_PIXEL_ADDR(SDL_VideoSurface->pixels, rect->x, rect->y,
SDL_VideoSurface->pitch, SDL_VideoSurface->format->BytesPerPixel);
dst_addr = PRZ_PIXEL_ADDR(this->hidden->buffer2, rect->x, rect->y, 2 * DWIDTH, 2);
dst_addr += this->hidden->offset;
odd_left = (this->hidden->win_x + rect->x) & 1;
odd_right = (this->hidden->win_x + rect->x + rect->w) & 1;
row_bytes = SDL_VideoSurface->format->BytesPerPixel * ((rect->x + rect->w > DWIDTH) ? DWIDTH : rect->w);
rows = (rect->y + rect->h > DHEIGHT) ? DHEIGHT : rect->h;
if ( ! this->hidden->cx && odd_right )
--row_bytes;
if ( this->hidden->cx ) {
if ( SDL_VideoSurface->format->BitsPerPixel == 16 ) {
/* 16 bpp SW, 16 bpp HW */
PRZ_DRAW_LOOP(
SDL_memcpy(dst_addr, src_addr, row_bytes);
);
}
dupdate();
}
}
}
#define PRZ_MAP_RGB(r, g, b) ((((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)))
static int PRZ_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
{
int i;
for ( i = firstcolor; i < firstcolor + ncolors; ++i )
prz_palette[i] = PRZ_MAP_RGB(colors[i].r, colors[i].g, colors[i].b);
return(1);
}
/* Note: If we are terminated, this could be called in the middle of
another SDL video routine -- notably UpdateRects.
*/
static void PRZ_VideoQuit(_THIS)
{
//NSP_DEBUG("Closing video");
}