/* unigraf.cpp - Universal Graphics interface (December 07, 2006) Copyright (c) 2002-2006, Alexander Shabarshin (alexander@shabarshin.com) This file is part of NedoPC SDK (www.nedopc.org). NedoPC SDK 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. NedoPC SDK 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 General Public License for more details. You should have received a copy of the GNU General Public License along with NedoPC SDK; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* You can use: -DSVGALIB for svgalib (text mode Linux) -DSDL for SDL library (Win32 or Linux) -DUNIFOPEN for external function fopen (UniFopen) */ #include #include #include #include #ifdef __WATCOMC__ #include #include #include #include #endif #ifdef SVGALIB #include #include #endif #ifdef SDL #include "SDL.h" #include "SDL_timer.h" #endif #include "unigraf.h" #ifdef FONT8X8 #include "font8x8a.h" #endif #ifdef FONT8X16 #include "font8x16.h" #endif #ifdef UNIFOPEN extern FILE* UniFopen(char *name, char *fmode); #define Fopen UniFopen #else #define Fopen fopen #endif #define LASTKEY 220 #define PRIV ((UniGrafPrivate*)PrivateData) struct UniGrafPrivate { int i; #ifdef SDL int SDLmodif,PALmodif,dx,dy; SDL_Surface *screen; SDL_Color col[256]; UniGrafPrivate(){screen=NULL;}; void ComplainAndExit(void) { fprintf(stderr, "SDL Problem: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } void SDLpixel(Sint32 X, Sint32 Y, Uint8 c) { if(X<0 || X>=dx || Y<0 || Y>=dy) return; Uint8 *bits; if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) return; } bits = ((Uint8 *)screen->pixels)+Y*screen->pitch+X; *((Uint8 *)(bits)) = c; if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } } #endif #ifdef __WATCOMC__ static char *keyPressed; void (__interrupt __far *KeyboardOldHandler)(); static void __interrupt __far KeyboardISR() { if(!keyPressed) return; int pi = inp(0x60); // read in scan code int pj = inp(0x61); // read in command status outp(0x61,pj|0x80); // reset the keyboard controller outp(0x61,pj); // if bit 7 (high bit) is set, the key was released if(pi&0x80) keyPressed[pi&0x7f]=0; // if bit 7 (high bit) is 0, the key just went down else keyPressed[pi&0x7f]=1; outp(0x20,0x20); } void KeyboardCapture(char *keys) { keyPressed = keys; KeyboardOldHandler = _dos_getvect(9); _dos_setvect(9,*KeyboardISR); } void KeyboardRelease(void) { _dos_setvect(9,KeyboardOldHandler); } #endif }; #ifdef __WATCOMC__ char* UniGrafPrivate::keyPressed = NULL; #endif UniGraf::UniGraf(int m,int w) { int mode = 0; graf = 0; PrivateData = new UniGrafPrivate; pal = new long[256]; keys = new char[LASTKEY]; graf = m; switch(graf) { case UG256_320x200: #ifdef __WATCOMC__ mode = 19; #endif #ifdef SVGALIB mode = 5; #endif #ifdef SDL dx = 320; dy = 200; mode = 1; #endif break; case UG256_640x400: #ifdef __WATCOMC__ mode = 0x100; #endif #ifdef SVGALIB mode = 9; #endif #ifdef SDL dx = 640; dy = 400; mode = 2; #endif break; case UG256_640x480: #ifdef __WATCOMC__ mode = 0x101; #endif #ifdef SVGALIB mode = 10; #endif #ifdef SDL dx = 640; dy = 480; mode = 3; #endif break; } mox = moy = mol = mom = mor = 0; for(int i=0;iKeyboardCapture(keys); _setvideomode(mode); _setbkcolor(0); videoconfig vc; _getvideoconfig(&vc); dx = vc.numxpixels; dy = vc.numypixels; #endif #ifdef SVGALIB vga_init(); if (!(vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_SET) & (1 << VGA_EXT_PAGE_OFFSET))) { puts("You need at least svgalib 1.2.10 to run this program!\n"); exit(1); } if (!vga_hasmode(mode)) return; vga_setmode(mode); vga_modeinfo *ginfo = vga_getmodeinfo(mode); dx = ginfo->width; dy = ginfo->height; if (keyboard_init()) { printf("Could not initialize keyboard.\n"); exit(1); } #endif #ifdef SDL PRIV->SDLmodif = 0; PRIV->PALmodif = 0; if(PrivateData==NULL) exit(1); if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) { PRIV->ComplainAndExit(); } PRIV->dx = dx; PRIV->dy = dy; unsigned long sdl_mode = SDL_SWSURFACE; if(!w) sdl_mode |= SDL_FULLSCREEN; #ifdef linux if(!w) sdl_mode |= SDL_HWPALETTE; #endif PRIV->screen = SDL_SetVideoMode(dx, dy, 8, sdl_mode); if ( PRIV->screen == NULL ) { PRIV->ComplainAndExit(); } printf("SDL Ok (%i)!\n",PRIV->screen->format->BytesPerPixel); #endif image = NULL; apy = NULL; if(!Screen()) graf = 0; } int UniGraf::Screen(int dxs,int dys) { #ifdef SDL PRIV->SDLmodif = 0; #endif if(dx<=0) return 0; if(dy<=0) return 0; dxscr = dxs; dyscr = dys; if(dxscr==0) dxscr=dx; if(dyscr==0) dyscr=dy; if(dx==dxscr) mx=1<<16; else mx = (dx<<16)/dxscr; if(dy==dyscr) my=1<<16; else my = (dy<<16)/dyscr; px = (short)(mx>>16); py = (short)(my>>16); if(mx&0xFFFF) px++; if(my&0xFFFF) py++; printf("mx=0x%8.8X my=0x%8.8X px=%i py=%i\n",mx,my,px,py); if(apy!=NULL) delete apy; apy = new short[dyscr]; if(apy==NULL) return 0; for(int i=0;i>16); if(image!=NULL) delete image; image = new unsigned char[dxscr*dyscr]; if(image==NULL) return 0; memset(image,0,dxscr*dyscr); return 1; } UniGraf::~UniGraf() { Close(); if(PrivateData!=NULL) delete PRIV; } void UniGraf::Close(void) { #ifdef SDL SDL_Quit(); #endif #ifdef __WATCOMC__ _setvideomode(-1); PRIV->KeyboardRelease(); #endif #ifdef SVGALIB vga_setmode(TEXT); keyboard_close(); #endif if(image!=NULL) { delete image; image = NULL; } if(pal!=NULL) { delete pal; pal = NULL; } if(apy!=NULL) { delete apy; apy = NULL; } if(keys!=NULL) { delete keys; keys = NULL; } graf = 0; } int UniGraf::SetPalette(int i,int r,int g,int b) { if(i<0 || i>255) return 0; pal[i] = r|(g<<8)|(b<<16); #ifdef __WATCOMC__ pal[i] = (pal[i]&0xFCFCFC)>>2; _remappalette(i,pal[i]); #endif #ifdef SVGALIB vga_setpalette(i,r>>2,g>>2,b>>2); #endif #ifdef SDL for(int j=0;j<256;j++) { PRIV->col[j].r = (pal[j]&0xFF); PRIV->col[j].g = ((pal[j]&0xFF00)>>8); PRIV->col[j].b = ((pal[j]&0xFF0000)>>16); } PRIV->SDLmodif = 1; PRIV->PALmodif = 1; #endif return 1; } long UniGraf::GetPalette(int i) { if(i<0 || i>255) return 0; return pal[i]; } int UniGraf::LoadPalette(char* s) { int b,g,r,i; char ss[100]; strcpy(ss,s); strcat(ss,".pal"); FILE *f=Fopen(ss,"rb"); if(f==NULL) return 0; for(i=0;i<256;i++) { r = fgetc(f)<<2; g = fgetc(f)<<2; b = fgetc(f)<<2; if(!SetPalette(i,r,g,b)){fclose(f);return 0;} } fclose(f); return 1; } int UniGraf::SetScreenPixel(int x,int y,int c) { if(x<0 || x>=dxscr || y<0 || y>=dyscr) return 0; #ifdef SDL Sint32 X, Y, X1, Y1; #endif image[x+y*dxscr] = c; int x0 = (x*mx)>>16; int y0 = (y*my)>>16; if(y==dxscr-1) py=dxscr-apy[dxscr-1]; else py=apy[y+1]-apy[y]; if(!py) py=1; for(int j=0;jSDLpixel(X,Y,c); #endif }} #ifdef SDL PRIV->SDLmodif = 1; #endif return 1; } int UniGraf::GetScreenPixel(int x,int y) { if(x<0 || x>=dxscr || y<0 || y>=dyscr) return 0; return image[x+y*dxscr]; } int UniGraf::DrawChar8x8(int x, int y, int c, int s, int b) { auto int k = 0; for(int i = 0; i < 8; i++) { #ifdef FONT8X8 k = font8x8[c][i]; #endif for (int j = 0; j < 8; j++) { if((k<=0) SetScreenPixel(x+j,y+i,b); } } return 1; } int UniGraf::DrawChar8x16(int x, int y, int c, int s, int b) { auto int k = 0; for(int i = 0; i < 16; i++) { #ifdef FONT8X16 k = font8x16[c][i]; #endif for(int j = 0; j < 8; j++) { if((k<=0) SetScreenPixel(x+j,y+i,b); } } return 1; } int UniGraf::DrawString(int x,int y,char *c,int h,int s,int b) { unsigned char *po = (unsigned char*) c; while(*po) { switch(h) { case 8: DrawChar8x8(x,y,*po,s,b); break; case 16: DrawChar8x16(x,y,*po,s,b); break; default: return 0; } po++; x += 8; } return 1; } int UniGraf::Update(void) { int ev = 0; #ifdef __WATCOMC__ for(int i=1;i<128;i++) if(keys[i]) ev=1; #endif #ifdef SVGALIB ev |= keyboard_update(); #endif #ifdef SDL if(PRIV->PALmodif) { SDL_SetColors(PRIV->screen,PRIV->col,0,256); } if(PRIV->SDLmodif) { SDL_UpdateRect(PRIV->screen,0,0,dx,dy); PRIV->SDLmodif = 0; } SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: #ifdef linux event.key.keysym.scancode-=8; if(event.key.keysym.scancode>0) #endif keys[event.key.keysym.scancode]=1; ev = 1; break; case SDL_KEYUP: #ifdef linux event.key.keysym.scancode-=8; if(event.key.keysym.scancode>0) #endif keys[event.key.keysym.scancode]=0; break; case SDL_MOUSEMOTION: mox = (int)((event.motion.x<<16)/mx); moy = (int)((event.motion.y<<16)/my); break; case SDL_MOUSEBUTTONDOWN: switch(event.button.button) { case 1: mol = 1; break; case 2: mom = 1; break; case 3: mor = 1; break; } mox = (int)((event.button.x<<16)/mx); moy = (int)((event.button.y<<16)/my); break; case SDL_MOUSEBUTTONUP: switch(event.button.button) { case 1: mol = 0; break; case 2: mom = 0; break; case 3: mor = 0; break; } break; } if(ev) break; } if(!ev) for(int j=1;j