258 lines
7.3 KiB
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");
|
|
}
|