X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsdl.c;h=97f8503f1b5d82bc3fe04efac970d5509f187222;hb=998be01ad92a672b69b11e24d472f6c0c076817f;hp=8e2ec948071686a17ba5f047c1edf16e28117bc0;hpb=da14f69fd95c7bd5a0d70cdf4935af06f1f20a04;p=rocksndiamonds.git diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c index 8e2ec948..97f8503f 100644 --- a/src/libgame/sdl.c +++ b/src/libgame/sdl.c @@ -1,39 +1,48 @@ /*********************************************************** -* Rocks'n'Diamonds -- McDuffin Strikes Back! * +* Artsoft Retro-Game Library * *----------------------------------------------------------* -* ©1995 Artsoft Development * -* Holger Schemel * -* 33659 Bielefeld-Senne * -* Telefon: (0521) 493245 * -* eMail: aeglos@valinor.owl.de * -* aeglos@uni-paderborn.de * -* q99492@pbhrzx.uni-paderborn.de * +* (c) 1994-2000 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * *----------------------------------------------------------* -* sdl.c * +* sdl.c * ***********************************************************/ -#include "libgame.h" +#include "system.h" +#include "misc.h" -#ifdef TARGET_SDL -inline void SDLInitBufferedDisplay(DrawBuffer *backbuffer, DrawWindow *window) +#if defined(TARGET_SDL) + +/* ========================================================================= */ +/* video functions */ +/* ========================================================================= */ + +inline void SDLInitVideoDisplay(void) { /* initialize SDL video */ if (SDL_Init(SDL_INIT_VIDEO) < 0) Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError()); - /* automatically cleanup SDL stuff after exit() */ + /* set default SDL depth */ + video.default_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel; + + /* set exit function to automatically cleanup SDL stuff after exit() */ atexit(SDL_Quit); +} +inline void SDLInitVideoBuffer(DrawBuffer *backbuffer, DrawWindow *window, + boolean fullscreen) +{ /* open SDL video output device (window or fullscreen mode) */ - if (!SDLSetVideoMode(backbuffer)) + if (!SDLSetVideoMode(backbuffer, fullscreen)) Error(ERR_EXIT, "setting video mode failed"); /* set window and icon title */ - SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING); - - /* create additional buffer for double-buffering */ - pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + SDL_WM_SetCaption(program.window_title, program.window_title); /* SDL cannot directly draw to the visible video framebuffer like X11, but always uses a backbuffer, which is then blitted to the visible @@ -48,22 +57,23 @@ inline void SDLInitBufferedDisplay(DrawBuffer *backbuffer, DrawWindow *window) buffer 'window' at the same size as the SDL backbuffer. Although it should never be drawn to directly, it would do no harm nevertheless. */ - *window = pix[PIX_DB_BACK]; /* 'window' is only symbolic buffer */ - pix[PIX_DB_BACK] = *backbuffer; /* 'backbuffer' is SDL screen buffer */ + /* create additional (symbolic) buffer for double-buffering */ + *window = CreateBitmap(video.width, video.height, video.depth); } inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) { boolean success = TRUE; + int surface_flags = SDL_HWSURFACE | (fullscreen ? SDL_FULLSCREEN : 0); if (fullscreen && !video.fullscreen_enabled && video.fullscreen_available) { /* switch display to fullscreen mode, if available */ DrawWindow window_old = *backbuffer; - DrawWindow window_new; + DrawWindow window_new = CreateBitmapStruct(); - if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH, - SDL_HWSURFACE|SDL_FULLSCREEN)) + if ((window_new->surface = SDL_SetVideoMode(video.width, video.height, + video.depth, surface_flags)) == NULL) { /* switching display to fullscreen mode failed */ @@ -76,7 +86,7 @@ inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) else { if (window_old) - SDL_FreeSurface(window_old); + FreeBitmap(window_old); *backbuffer = window_new; video.fullscreen_enabled = TRUE; @@ -88,10 +98,10 @@ inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) { /* switch display to window mode */ DrawWindow window_old = *backbuffer; - DrawWindow window_new; + DrawWindow window_new = CreateBitmapStruct(); - if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH, - SDL_HWSURFACE)) + if ((window_new->surface = SDL_SetVideoMode(video.width, video.height, + video.depth, surface_flags)) == NULL) { /* switching display to window mode failed -- should not happen */ @@ -102,7 +112,7 @@ inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) else { if (window_old) - SDL_FreeSurface(window_old); + FreeBitmap(window_old); *backbuffer = window_new; video.fullscreen_enabled = FALSE; @@ -113,12 +123,12 @@ inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, boolean fullscreen) return success; } -inline void SDLCopyArea(SDL_Surface *src_surface, SDL_Surface *dst_surface, +inline void SDLCopyArea(Bitmap src_bitmap, Bitmap dst_bitmap, int src_x, int src_y, int width, int height, - int dst_x, int dst_y) + int dst_x, int dst_y, int copy_mode) { - SDL_Surface *surface = (dst_surface == window ? backbuffer : dst_surface); + Bitmap real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap); SDL_Rect src_rect, dst_rect; src_rect.x = src_x; @@ -131,17 +141,19 @@ inline void SDLCopyArea(SDL_Surface *src_surface, SDL_Surface *dst_surface, dst_rect.w = width; dst_rect.h = height; - if (src_surface != backbuffer || dst_surface != window) - SDL_BlitSurface(src_surface, &src_rect, surface, &dst_rect); + if (src_bitmap != backbuffer || dst_bitmap != window) + SDL_BlitSurface((copy_mode == SDLCOPYAREA_MASKED ? + src_bitmap->surface_masked : src_bitmap->surface), + &src_rect, real_dst_bitmap->surface, &dst_rect); - if (dst_surface == window) - SDL_UpdateRect(backbuffer, dst_x, dst_y, width, height); + if (dst_bitmap == window) + SDL_UpdateRect(backbuffer->surface, dst_x, dst_y, width, height); } -inline void SDLFillRectangle(SDL_Surface *dst_surface, int x, int y, +inline void SDLFillRectangle(Bitmap dst_bitmap, int x, int y, int width, int height, unsigned int color) { - SDL_Surface *surface = (dst_surface == window ? backbuffer : dst_surface); + Bitmap real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap); SDL_Rect rect; unsigned int color_r = (color >> 16) && 0xff; unsigned int color_g = (color >> 8) && 0xff; @@ -152,11 +164,12 @@ inline void SDLFillRectangle(SDL_Surface *dst_surface, int x, int y, rect.w = width; rect.h = height; - SDL_FillRect(surface, &rect, - SDL_MapRGB(surface->format, color_r, color_g, color_b)); + SDL_FillRect(real_dst_bitmap->surface, &rect, + SDL_MapRGB(real_dst_bitmap->surface->format, + color_r, color_g, color_b)); - if (dst_surface == window) - SDL_UpdateRect(backbuffer, x, y, width, height); + if (dst_bitmap == window) + SDL_UpdateRect(backbuffer->surface, x, y, width, height); } inline void SDLDrawSimpleLine(SDL_Surface *surface, int from_x, int from_y, @@ -182,6 +195,494 @@ inline void SDLDrawSimpleLine(SDL_Surface *surface, int from_x, int from_y, SDL_MapRGB(surface->format, color_r, color_g, color_b)); } +inline void SDLDrawLine(SDL_Surface *surface, int from_x, int from_y, + int to_x, int to_y, Uint32 color) +{ + sge_Line(surface, from_x, from_y, to_x, to_y, color); +} + +#if 0 +inline void SDLDrawLines(SDL_Surface *surface, struct XY *points, + int num_points, Uint32 color) +{ + int i, x, y; + int line_width = 4; + + for (i=0; i= 0 && x <= surface->w - 1 && y >= 0 && y <= surface->h - 1) + { + switch (surface->format->BytesPerPixel) + { + case 1: + { + /* Assuming 8-bpp */ + *((Uint8 *)surface->pixels + y*surface->pitch + x) = color; + } + break; + + case 2: + { + /* Probably 15-bpp or 16-bpp */ + *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color; + } + break; + + case 3: + { + /* Slow 24-bpp mode, usually not used */ + Uint8 *pix; + int shift; + + /* Gack - slow, but endian correct */ + pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; + shift = surface->format->Rshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Gshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Bshift; + *(pix+shift/8) = color>>shift; + } + break; + + case 4: + { + /* Probably 32-bpp */ + *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color; + } + break; + } + } +} + +void _PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y, + Uint8 R, Uint8 G, Uint8 B) +{ + _PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B)); +} + +void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + *((Uint8 *)surface->pixels + y*surface->pitch + x) = color; +} + +void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color; +} + +void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + Uint8 *pix; + int shift; + + /* Gack - slow, but endian correct */ + pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3; + shift = surface->format->Rshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Gshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Bshift; + *(pix+shift/8) = color>>shift; +} + +void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color; +} + +void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color) +{ + switch (dest->format->BytesPerPixel) + { + case 1: + *((Uint8 *)dest->pixels + y*dest->pitch + x) = color; + break; + + case 2: + *((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color; + break; + + case 3: + _PutPixel24(dest,x,y,color); + break; + + case 4: + *((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color; + break; + } +} + +void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color) +{ + if (SDL_MUSTLOCK(surface)) + { + if (SDL_LockSurface(surface) < 0) + { + return; + } + } + + _PutPixel(surface, x, y, color); + + if (SDL_MUSTLOCK(surface)) + { + SDL_UnlockSurface(surface); + } +} + +void sge_PutPixelRGB(SDL_Surface *surface, Sint16 x, Sint16 y, + Uint8 R, Uint8 G, Uint8 B) +{ + sge_PutPixel(surface, x, y, SDL_MapRGB(surface->format, R, G, B)); +} + +Sint32 sge_CalcYPitch(SDL_Surface *dest, Sint16 y) +{ + if (y >= 0 && y <= dest->h - 1) + { + switch (dest->format->BytesPerPixel) + { + case 1: + return y*dest->pitch; + break; + + case 2: + return y*dest->pitch/2; + break; + + case 3: + return y*dest->pitch; + break; + + case 4: + return y*dest->pitch/4; + break; + } + } + + return -1; +} + +void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color) +{ + if (x >= 0 && x <= surface->w - 1 && ypitch >= 0) + { + switch (surface->format->BytesPerPixel) + { + case 1: + { + /* Assuming 8-bpp */ + *((Uint8 *)surface->pixels + ypitch + x) = color; + } + break; + + case 2: + { + /* Probably 15-bpp or 16-bpp */ + *((Uint16 *)surface->pixels + ypitch + x) = color; + } + break; + + case 3: + { + /* Slow 24-bpp mode, usually not used */ + Uint8 *pix; + int shift; + + /* Gack - slow, but endian correct */ + pix = (Uint8 *)surface->pixels + ypitch + x*3; + shift = surface->format->Rshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Gshift; + *(pix+shift/8) = color>>shift; + shift = surface->format->Bshift; + *(pix+shift/8) = color>>shift; + } + break; + + case 4: + { + /* Probably 32-bpp */ + *((Uint32 *)surface->pixels + ypitch + x) = color; + } + break; + } + } +} + +void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, + Uint32 Color) +{ + SDL_Rect l; + + if (SDL_MUSTLOCK(Surface)) + { + if (SDL_LockSurface(Surface) < 0) + { + return; + } + } + + if (x1 > x2) + { + Sint16 tmp = x1; + x1 = x2; + x2 = tmp; + } + + /* Do the clipping */ + if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0) + return; + if (x1 < 0) + x1 = 0; + if (x2 > Surface->w - 1) + x2 = Surface->w - 1; + + l.x = x1; + l.y = y; + l.w = x2 - x1 + 1; + l.h = 1; + + SDL_FillRect(Surface, &l, Color); + + if (SDL_MUSTLOCK(Surface)) + { + SDL_UnlockSurface(Surface); + } +} + +void sge_HLineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, + Uint8 R, Uint8 G, Uint8 B) +{ + sge_HLine(Surface, x1, x2, y, SDL_MapRGB(Surface->format, R, G, B)); +} + +void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color) +{ + SDL_Rect l; + + if (x1 > x2) + { + Sint16 tmp = x1; + x1 = x2; + x2 = tmp; + } + + /* Do the clipping */ + if (y < 0 || y > Surface->h - 1 || x1 > Surface->w - 1 || x2 < 0) + return; + if (x1 < 0) + x1 = 0; + if (x2 > Surface->w - 1) + x2 = Surface->w - 1; + + l.x = x1; + l.y = y; + l.w = x2 - x1 + 1; + l.h = 1; + + SDL_FillRect(Surface, &l, Color); +} + +void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, + Uint32 Color) +{ + SDL_Rect l; + + if (SDL_MUSTLOCK(Surface)) + { + if (SDL_LockSurface(Surface) < 0) + { + return; + } + } + + if (y1 > y2) + { + Sint16 tmp = y1; + y1 = y2; + y2 = tmp; + } + + /* Do the clipping */ + if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0) + return; + if (y1 < 0) + y1 = 0; + if (y2 > Surface->h - 1) + y2 = Surface->h - 1; + + l.x = x; + l.y = y1; + l.w = 1; + l.h = y2 - y1 + 1; + + SDL_FillRect(Surface, &l, Color); + + if (SDL_MUSTLOCK(Surface)) + { + SDL_UnlockSurface(Surface); + } +} + +void sge_VLineRGB(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, + Uint8 R, Uint8 G, Uint8 B) +{ + sge_VLine(Surface, x, y1, y2, SDL_MapRGB(Surface->format, R, G, B)); +} + +void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color) +{ + SDL_Rect l; + + if (y1 > y2) + { + Sint16 tmp = y1; + y1 = y2; + y2 = tmp; + } + + /* Do the clipping */ + if (x < 0 || x > Surface->w - 1 || y1 > Surface->h - 1 || y2 < 0) + return; + if (y1 < 0) + y1 = 0; + if (y2 > Surface->h - 1) + y2 = Surface->h - 1; + + l.x = x; + l.y = y1; + l.w = 1; + l.h = y2 - y1 + 1; + + SDL_FillRect(Surface, &l, Color); +} + +void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1, + Sint16 x2, Sint16 y2, Uint32 Color, + void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, + Uint32 Color)) +{ + Sint16 dx, dy, sdx, sdy, x, y, px, py; + + dx = x2 - x1; + dy = y2 - y1; + + sdx = (dx < 0) ? -1 : 1; + sdy = (dy < 0) ? -1 : 1; + + dx = sdx * dx + 1; + dy = sdy * dy + 1; + + x = y = 0; + + px = x1; + py = y1; + + if (dx >= dy) + { + for (x = 0; x < dx; x++) + { + Callback(Surface, px, py, Color); + + y += dy; + if (y >= dx) + { + y -= dx; + py += sdy; + } + + px += sdx; + } + } + else + { + for (y = 0; y < dy; y++) + { + Callback(Surface, px, py, Color); + + x += dx; + if (x >= dy) + { + x -= dy; + px += sdx; + } + + py += sdy; + } + } +} + +void sge_DoLineRGB(SDL_Surface *Surface, Sint16 X1, Sint16 Y1, + Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B, + void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, + Uint32 Color)) +{ + sge_DoLine(Surface, X1, Y1, X2, Y2, + SDL_MapRGB(Surface->format, R, G, B), Callback); +} + +void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, + Uint32 Color) +{ + if (SDL_MUSTLOCK(Surface)) + { + if (SDL_LockSurface(Surface) < 0) + return; + } + + /* Draw the line */ + sge_DoLine(Surface, x1, y1, x2, y2, Color, _PutPixel); + + /* unlock the display */ + if (SDL_MUSTLOCK(Surface)) + { + SDL_UnlockSurface(Surface); + } +} + +void sge_LineRGB(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, + Sint16 y2, Uint8 R, Uint8 G, Uint8 B) +{ + sge_Line(Surface, x1, y1, x2, y2, SDL_MapRGB(Surface->format, R, G, B)); +} + + +/* ========================================================================= */ +/* audio functions */ +/* ========================================================================= */ + inline boolean SDLOpenAudio(void) { if (SDL_Init(SDL_INIT_AUDIO) < 0)