📄 sdl_gemvideo.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_gemvideo.c,v 1.5 2002/10/05 16:27:56 slouken Exp $";#endif/* * GEM SDL video driver implementation * inspired from the Dummy SDL driver * * Patrice Mandin * and work from * Olivier Landemarre, Johan Klockars, Xavier Joubert, Claude Attard */#include <stdio.h>#include <stdlib.h>#include <string.h>/* Mint includes */#include <gem.h>#include <gemx.h>#include <mint/osbind.h>#include <sys/cookie.h>#include "SDL.h"#include "SDL_error.h"#include "SDL_video.h"#include "SDL_mouse.h"#include "SDL_sysvideo.h"#include "SDL_pixels_c.h"#include "SDL_events_c.h"#include "SDL_cursor_c.h"#include "SDL_ataric2p_s.h"#include "SDL_ataric2p060_c.h"#include "SDL_atarieddi_s.h"#include "SDL_atarimxalloc_c.h"#include "SDL_gemvideo.h"#include "SDL_gemevents_c.h"#include "SDL_gemmouse_c.h"#include "SDL_gemwm_c.h"#include "SDL_xbiosevents_c.h"/* Defines */#define GEM_VID_DRIVER_NAME "gem"/* Variables */static unsigned char vdi_index[256] = { 0, 2, 3, 6, 4, 7, 5, 8, 9, 10, 11, 14, 12, 15, 13, 255};static const unsigned char empty_name[]="";/* Initialization/Query functions */static int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat);static SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);static SDL_Surface *GEM_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);static int GEM_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors);static void GEM_VideoQuit(_THIS);/* Hardware surface functions */static int GEM_AllocHWSurface(_THIS, SDL_Surface *surface);static int GEM_LockHWSurface(_THIS, SDL_Surface *surface);static int GEM_FlipHWSurface(_THIS, SDL_Surface *surface);static void GEM_UnlockHWSurface(_THIS, SDL_Surface *surface);static void GEM_FreeHWSurface(_THIS, SDL_Surface *surface);static void GEM_UpdateRects(_THIS, int numrects, SDL_Rect *rects);#if 0static int GEM_ToggleFullScreen(_THIS, int on);#endif/* Internal functions */static void GEM_FreeBuffers(_THIS);static void GEM_ClearScreen(_THIS);static void GEM_LockScreen(_THIS);static void GEM_UnlockScreen(_THIS);static void refresh_window(_THIS, int winhandle, short *rect);/* GEM driver bootstrap functions */static int GEM_Available(void){ short ap_id; const char *envr = getenv("SDL_VIDEODRIVER"); /* Check if user asked a different video driver */ if ((envr) && (strcmp(envr, GEM_VID_DRIVER_NAME)!=0)) { return 0; } /* Test if AES available */ ap_id = appl_init(); if (ap_id == -1) return 0; appl_exit(); return 1;}static void GEM_DeleteDevice(SDL_VideoDevice *device){ free(device->hidden); free(device);}static SDL_VideoDevice *GEM_CreateDevice(int devindex){ SDL_VideoDevice *device; /* Initialize all variables that we clean on shutdown */ device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice)); if ( device ) { memset(device, 0, (sizeof *device)); device->hidden = (struct SDL_PrivateVideoData *) malloc((sizeof *device->hidden)); } if ( (device == NULL) || (device->hidden == NULL) ) { SDL_OutOfMemory(); if ( device ) { free(device); } return(0); } memset(device->hidden, 0, (sizeof *device->hidden)); atari_test_cpu060_present(); /* Set the function pointers */ device->VideoInit = GEM_VideoInit; device->ListModes = GEM_ListModes; device->SetVideoMode = GEM_SetVideoMode; device->SetColors = GEM_SetColors; device->UpdateRects = NULL /*GEM_UpdateRects*/; device->VideoQuit = GEM_VideoQuit; device->AllocHWSurface = GEM_AllocHWSurface; device->LockHWSurface = GEM_LockHWSurface; device->UnlockHWSurface = GEM_UnlockHWSurface; device->FlipHWSurface = GEM_FlipHWSurface; device->FreeHWSurface = GEM_FreeHWSurface; device->ToggleFullScreen = NULL /*GEM_ToggleFullScreen*/; /* Window manager */ device->SetCaption = GEM_SetCaption; device->SetIcon = NULL /*GEM_SetIcon*/; device->IconifyWindow = GEM_IconifyWindow; device->GrabInput = GEM_GrabInput; /* Events */ device->InitOSKeymap = GEM_InitOSKeymap; device->PumpEvents = GEM_PumpEvents; /* Mouse */ device->FreeWMCursor = GEM_FreeWMCursor; device->CreateWMCursor = GEM_CreateWMCursor; device->ShowWMCursor = GEM_ShowWMCursor; device->WarpWMCursor = NULL /*GEM_WarpWMCursor*/; device->CheckMouseMode = GEM_CheckMouseMode; /* Joystick + Mouse relative motion */ SDL_AtariXbios_InstallVectors(ATARI_XBIOS_MOUSEEVENTS|ATARI_XBIOS_JOYSTICKEVENTS); device->free = GEM_DeleteDevice; return device;}VideoBootStrap GEM_bootstrap = { GEM_VID_DRIVER_NAME, "Atari GEM video driver", GEM_Available, GEM_CreateDevice};static void VDI_ReadExtInfo(_THIS, short *work_out){ unsigned long EdDI_version; unsigned long cookie_EdDI; Uint32 num_colours; Uint16 clut_type, num_bits; /* Read EdDI informations */ if (Getcookie(C_EdDI, &cookie_EdDI) == C_NOTFOUND) { return; } EdDI_version = Atari_get_EdDI_version( (void *)cookie_EdDI); vq_scrninfo(VDI_handle, work_out); VDI_format = work_out[0]; clut_type = work_out[1]; num_bits = work_out[2]; num_colours = *((Uint32 *) &work_out[3]); /* With EdDI>=1.1, we can have screen pitch, address and format * so we can directly write to screen without using vro_cpyfm */ if (EdDI_version >= EDDI_11) { VDI_pitch = work_out[5]; VDI_screen = (void *) *((unsigned long *) &work_out[6]); switch(num_colours) { case 32768UL: if (work_out[14] & (1<<7)) { /* Little endian */ if (work_out[14] & (1<<1)) { /* Falcon */ VDI_alphamask = 1 << 13; VDI_redmask = 31 << 3; VDI_greenmask = (3 << 14) | 7; VDI_bluemask = 31 << 8; } else { /* Others */ VDI_alphamask = 1 << 7; VDI_redmask = 31 << 2; VDI_greenmask = (7 << 13) | 3; VDI_bluemask = 31 << 8; } } else { /* Big endian */ if (work_out[14] & (1<<1)) { /* Falcon */ VDI_alphamask = 1 << 5; VDI_redmask = 31 << 11; VDI_greenmask = 31 << 6; VDI_bluemask = 31; } else { /* Others */ VDI_alphamask = 1 << 15; VDI_redmask = 31 << 10; VDI_greenmask = 31 << 5; VDI_bluemask = 31; } } break; case 65536UL: if (work_out[14] & (1<<7)) { /* Little endian */ VDI_alphamask = 0; VDI_redmask = 31 << 3; VDI_greenmask = (7 << 13) | 7; VDI_bluemask = 31 << 8; } else { /* Big endian */ VDI_alphamask = 0; VDI_redmask = 31 << 11; VDI_greenmask = 63 << 5; VDI_bluemask = 31; } break; case 16777216UL: if (work_out[14] & (1<<7)) { /* Little endian */ switch(num_bits) { case 24: VDI_alphamask = 0; VDI_redmask = 255; VDI_greenmask = 255 << 8; VDI_bluemask = 255 << 16; break; case 32: VDI_alphamask = 255; VDI_redmask = 255 << 8; VDI_greenmask = 255 << 16; VDI_bluemask = 255 << 24; break; } } else { /* Big endian */ switch(num_bits) { case 24: VDI_alphamask = 0; VDI_redmask = 255 << 16; VDI_greenmask = 255 << 8; VDI_bluemask = 255; break; case 32: VDI_alphamask = 255 << 24; VDI_redmask = 255 << 16; VDI_greenmask = 255 << 8; VDI_bluemask = 255; break; } } break; } } switch(clut_type) { case VDI_CLUT_HARDWARE: { int i; Uint16 *tmp_p; tmp_p = (Uint16 *)&work_out[16]; for (i=0;i<256;i++) { vdi_index[*tmp_p++] = i; } } break; case VDI_CLUT_SOFTWARE: if (EdDI_version < EDDI_11) { int component; /* red, green, blue, alpha, overlay */ int num_bit; unsigned short *tmp_p; /* We can build masks with info here */ tmp_p = (unsigned short *) &work_out[16]; for (component=0;component<5;component++) { for (num_bit=0;num_bit<16;num_bit++) { unsigned short valeur; valeur = *tmp_p++; if (valeur == 0xffff) { continue; } switch(component) { case 0: VDI_redmask |= 1<< valeur; break; case 1: VDI_greenmask |= 1<< valeur; break; case 2: VDI_bluemask |= 1<< valeur; break; case 3: VDI_alphamask |= 1<< valeur; break; } } } } /* Remove lower green bits for Intel endian screen */ if ((VDI_greenmask == ((7<<13)|3)) || (VDI_greenmask == ((7<<13)|7))) { VDI_greenmask &= ~(7<<13); } break; case VDI_CLUT_NONE: break; }}int GEM_VideoInit(_THIS, SDL_PixelFormat *vformat){ int i; short work_in[12], work_out[272], dummy; /* Open AES (Application Environment Services) */ GEM_ap_id = appl_init(); if (GEM_ap_id == -1) { fprintf(stderr,"Can not open AES\n"); return 1; } /* Read version and features */ GEM_version = aes_global[0]; if (GEM_version >= 0x0400) { short ap_gout[4]; GEM_wfeatures=0; if (appl_getinfo(AES_WINDOW, &ap_gout[0], &ap_gout[1], &ap_gout[2], &ap_gout[3])==0) { GEM_wfeatures=ap_gout[0]; } } /* Ask VDI physical workstation handle opened by AES */ VDI_handle = graf_handle(&dummy, &dummy, &dummy, &dummy); if (VDI_handle<1) { fprintf(stderr,"Wrong VDI handle %d returned by AES\n",VDI_handle); return 1; } /* Open virtual VDI workstation */ work_in[0]=Getrez()+2; for(i = 1; i < 10; i++) work_in[i] = 1; work_in[10] = 2; v_opnvwk(work_in, &VDI_handle, work_out); if (VDI_handle == 0) { fprintf(stderr,"Can not open VDI virtual workstation\n"); return 1; } /* Read fullscreen size */ VDI_w = work_out[0] + 1; VDI_h = work_out[1] + 1; /* Read desktop size and position */ if (!wind_get(DESKTOP_HANDLE, WF_WORKXYWH, &GEM_desk_x, &GEM_desk_y, &GEM_desk_w, &GEM_desk_h)) { fprintf(stderr,"Can not read desktop properties\n"); return 1; } /* Read bit depth */ vq_extnd(VDI_handle, 1, work_out); VDI_bpp = work_out[4]; VDI_oldnumcolors=0; switch(VDI_bpp) { case 8: VDI_pixelsize=1; break; case 15: case 16: VDI_pixelsize=2; break; case 24: VDI_pixelsize=3; break; case 32: VDI_pixelsize=4; break; default: fprintf(stderr,"%d bits colour depth not supported\n",VDI_bpp); return 1; } /* Setup hardware -> VDI palette mapping */ for(i = 16; i < 255; i++) { vdi_index[i] = i; } vdi_index[255] = 1; /* Save current palette */ if (VDI_bpp>8) { VDI_oldnumcolors=1<<8; } else { VDI_oldnumcolors=1<<VDI_bpp; } for(i = 0; i < VDI_oldnumcolors; i++) { short rgb[3]; vq_color(VDI_handle, i, 0, rgb); VDI_oldpalette[i][0] = rgb[0]; VDI_oldpalette[i][1] = rgb[1]; VDI_oldpalette[i][2] = rgb[2]; } /* Setup screen info */ GEM_title_name = empty_name; GEM_icon_name = empty_name; GEM_handle = -1; GEM_locked = SDL_FALSE; GEM_win_fulled = SDL_FALSE; VDI_screen = NULL; VDI_ReadExtInfo(this, work_out); if (VDI_screen == NULL) { VDI_pitch = VDI_w * VDI_pixelsize; VDI_format = VDI_FORMAT_UNKNOWN; VDI_redmask = VDI_greenmask = VDI_bluemask = VDI_alphamask = 0; } /* Setup destination mfdb */ VDI_dst_mfdb.fd_addr = NULL; /* Update hardware info */ this->info.hw_available = 0; this->info.video_mem = 0; /* TC, screen : no shadow (direct) * 8P, screen: no shadow (direct) * 8I, screen: shadow, c2p (shadow -> c2p) * TC, no screen: shadow (vro_cpyfm) * 8P, no screen: shadow (vro_cpyfm) * 8I/U, no screen: shadow, shadow_c2p, c2p (shadow -> c2p -> vro_cpyfm) */ /* Determine the screen depth */ /* we change this during the SDL_SetVideoMode implementation... */ vformat->BitsPerPixel = VDI_bpp; /* Set mouse cursor to arrow */ graf_mouse(ARROW, NULL); /* Init chunky to planar routine */ Atari_C2pInit = Atari_C2pInit8; if (atari_cpu060_avail) { Atari_C2pConvert = Atari_C2pConvert8_060; } else { Atari_C2pConvert = Atari_C2pConvert8; } Atari_C2pInit(); /* We're done! */ return(0);}SDL_Rect **GEM_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags){ if (format->BitsPerPixel == VDI_bpp) { return((SDL_Rect **)-1); } else { return ((SDL_Rect **)NULL); }}static void GEM_FreeBuffers(_THIS){ /* Release buffer */ if ( GEM_buffer ) { free( GEM_buffer ); GEM_buffer=NULL; } /* Destroy window */ if (GEM_handle>=0) { wind_close(GEM_handle); wind_delete(GEM_handle); GEM_handle=-1; }}static void GEM_ClearScreen(_THIS){ short rgb[3]={0,0,0}; short oldrgb[3]; short pxy[4]; v_hide_c(VDI_handle); vq_color(VDI_handle, vdi_index[0], 0, oldrgb); vs_color(VDI_handle, vdi_index[0], rgb); pxy[0] = pxy[1] = 0; pxy[2] = VDI_w - 1; pxy[3] = VDI_h - 1; vsf_color(VDI_handle,0); vsf_interior(VDI_handle,1); vsf_perimeter(VDI_handle,0); v_bar(VDI_handle,pxy); vs_color(VDI_handle, vdi_index[0], oldrgb);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -