#include #include #include #include #include "bomber.h" #include "gfx.h" #define MAXCOLORS 256 int usedcolors = 0; SDL_Surface* thescreen; SDL_Color themap[256]; uchar* videomem; int stride; int mousex, mousey, mouseb; uchar mustlock = 0, locked = 0; uchar* block64; int buttonstate = 0, buttondown = 0; int mxpos, mypos; int pressedcodes[KEYMAX], downcodes[KEYMAX], numpressed, numdown; void dumpgfx() { usedcolors = 0; } static int bestmatch(int red, int green, int blue) { int i; int bestcolor, bestdelta = 0; int rdelta, gdelta, bdelta; int delta; i = 0; bestcolor = -1; while (i < usedcolors) { rdelta = themap[i].r; rdelta -= red; rdelta *= rdelta; gdelta = themap[i].g; gdelta -= green; gdelta *= gdelta; bdelta = themap[i].b; bdelta -= blue; bdelta *= bdelta; delta = rdelta + gdelta + bdelta; if (bestcolor < 0 || delta < bestdelta) { bestdelta = delta; bestcolor = i; } i++; } return bestcolor; } static void updatemap(void) { SDL_SetColors(thescreen, themap, 0, 256); } void createinout(gfxset* gs) { uchar* p; int i, j, counts[256]; uchar red, green, blue; int cnt; p = gs->gs_pic; for (i = 0; i < 256; i++) counts[i] = 0; i = gs->gs_xsize * gs->gs_ysize; while (i--) counts[*p++]++; cnt = 0; gs->gs_inout[0] = 0; for (i = 1; i < 256; i++) { if (counts[i]) { cnt++; p = gs->gs_colormap + i + i + i; red = *p++; green = *p++; blue = *p++; for (j = 0; j < usedcolors; j++) { if (red == themap[j].r && green == themap[j].g && blue == themap[j].b) { gs->gs_inout[i] = j; break; } } if (j == usedcolors) { if (usedcolors < MAXCOLORS) { themap[j].r = red; themap[j].g = green; themap[j].b = blue; gs->gs_inout[i] = usedcolors; ++usedcolors; } else gs->gs_inout[i] = bestmatch(red, green, blue); } } } updatemap(); } static uchar* compressfig(uchar* put, gfxset* gs, int sourcex, int sourcey, int sizex, int sizey) { int j, gswidth; uchar *p, *p2, pixel, *map1; int dx, dy; gswidth = gs->gs_xsize; map1 = gs->gs_inout; p = gs->gs_pic + sourcex + gswidth * sourcey; for (dy = 0; dy < sizey; dy++) { p2 = p; j = 0; for (dx = 0; dx <= sizex; dx++) { if (dx < sizex) pixel = *p2; else pixel = 0; ++p2; if (pixel) ++j; else if (j) { *put++ = j; *put++ = dx - j; *put++ = dy; p2 -= j + 1; while (j) *put++ = map1[*p2++], --j; ++p2; } } p += gswidth; } *put++ = 0; return put; } static void gfxfetchsingle(figure* fig, gfxset* gs, int sourcex, int sourcey, int sizex, int sizey) { uchar *p, *p2; int dx, dy; /* uchar *map1; */ int gswidth; int minx, miny, maxx, maxy; int tx, ty; /* map1=gs->gs_inout; */ gswidth = gs->gs_xsize; p = gs->gs_pic + sourcex + gswidth * sourcey; minx = miny = maxx = maxy = -1; for (dy = 0; dy < sizey; dy++) { p2 = p; ty = sourcey + dy; for (dx = 0; dx < sizex; dx++) { if (!*p2++) continue; if (miny == -1 || ty < miny) miny = ty; if (maxy == -1 || ty > maxy) maxy = ty; tx = sourcex + dx; if (minx == -1 || tx < minx) minx = tx; if (maxx == -1 || tx > maxx) maxx = tx; } p += gswidth; } if (minx == -1) { minx = maxx = sourcex; miny = maxy = sourcey; } fig->xdelta = minx - sourcex; fig->ydelta = miny - sourcey; sourcex = minx; sourcey = miny; fig->xsize = sizex = maxx - minx + 1; fig->ysize = sizey = maxy - miny + 1; p = compressfig(block64, gs, sourcex, sourcey, sizex, sizey); fig->graphics = malloc(p - block64); if (fig->graphics) memcpy(fig->graphics, block64, p - block64); } //(gfxset *gs,figure *fig,int sourcex,int sourcey,int sizex,int sizey) void gfxfetch(gfxset* gs, figure* fig, int num) { int x, y; int xsize, ysize; int fxsize, fysize; unsigned char *p, *p2; xsize = gs->gs_xsize; ysize = gs->gs_ysize; p2 = p = gs->gs_pic + xsize + 1; fxsize = 2; while (*p++ == 0) ++fxsize; fysize = 2; while (*p2 == 0) ++fysize, p2 += xsize; x = fxsize; y = 0; while (num--) { gfxfetchsingle(fig, gs, x, y, fxsize, fysize); x += fxsize; if (x > xsize - fxsize) { x = 0; y += fysize; if (y > ysize - fysize) y = 0; } fig++; } } void solidfetch(gfxset* gs, solid* dest) { int xsize, ysize; int i; unsigned char *p, *map; uchar* gfx; memset(dest, 0, sizeof(solid)); xsize = gs->gs_xsize; ysize = gs->gs_ysize; i = xsize * ysize; gfx = dest->graphics = malloc(i); if (!gfx) return; dest->xsize = xsize; dest->ysize = ysize; map = gs->gs_inout; memcpy(gfx, gs->gs_pic, i); p = gfx; while (i--) { if (*p) *p = map[*p]; ++p; } } void solidcopyany(solid* src, solid* dest, int destx, int desty, int sizex, int sizey) { int xmax, ymax; int j; uchar *p1, *p2; int w; xmax = src->xsize; ymax = src->ysize; if (destx >= xmax || desty >= ymax || destx + sizex <= 0 || desty + sizey <= 0) return; if (destx < 0) { sizex += destx; destx = 0; } if (desty < 0) { sizey += desty; desty = 0; } if (destx + sizex > xmax) sizex = xmax - destx; if (desty + sizey > ymax) sizey = ymax - desty; if (dest) { w = dest->xsize; p1 = dest->graphics + desty * w + destx; } else { gfxlock(); w = stride; p1 = videomem + desty * stride + destx; } p2 = src->graphics + desty * xmax + destx; for (j = 0; j < sizey; ++j) { memcpy(p1, p2, sizex); p1 += w; p2 += xmax; } } void solidcopy(solid* solid, int destx, int desty, int sizex, int sizey) { solidcopyany(solid, 0, destx, desty, sizex, sizey); } void drawfigureany(int x, int y, figure* fig, solid* dest) { int run; int dx, dy; int xsize, ysize; int clipx, clipy, w; unsigned char *pc, *p, *p2, *take; take = fig->graphics; if (dest) { w = clipx = dest->xsize; clipy = dest->ysize; pc = dest->graphics; } else { gfxlock(); w = stride; clipx = IXSIZE; clipy = IYSIZE; pc = videomem; } dx = fig->xdelta; dy = fig->ydelta; xsize = fig->xsize; ysize = fig->ysize; x += dx; y += dy; if (x >= 0 && y >= 0 && x <= clipx - xsize && y <= clipy - ysize) { while ((run = *take++)) { dx = *((signed char*) take); ++take; dy = *((signed char*) take); ++take; p = pc + w * (y + dy) + x + dx; while (run--) *p++ = *take++; } } else { while ((run = *take++)) { dx = *((signed char*) take); ++take; dy = *((signed char*) take); ++take; dx += x; dy += y; p2 = take; take += run; if (dy < 0 || dy >= clipy) continue; if (dx >= clipx) continue; if (dx < 0) { p2 -= dx; run += dx; dx = 0; } else if (dx + run > clipx) run = clipx - dx; p = pc + w * dy + dx; if (run) memcpy(p, p2, run); } } } void drawfigure(int destx, int desty, figure* fig) { drawfigureany(destx, desty, fig, 0); } void copyup() { gfxunlock(); SDL_UpdateRect(thescreen, 0, 0, 0, 0); needwhole = 0; } void copyupxy(int x, int y) { gfxunlock(); SDL_UpdateRect(thescreen, x, y, 24, 24); } void copyupxysize(int x, int y, int xsize, int ysize) { gfxunlock(); SDL_UpdateRect(thescreen, x, y, xsize, ysize); } // static void set_color(int color, int red, int green, int blue) { // themap[color].r=red; // themap[color].g=green; // themap[color].b=blue; // } void opengfx(void) { unsigned long videoflags; themap[0].r = 0; themap[0].g = 0; themap[0].b = 0; usedcolors = 1; block64 = malloc(65536); if (!block64) { printf("Couldn't allocate block64\n"); exit(50); } if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) { fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); exit(1); } videoflags = SDL_SWSURFACE | SDL_HWPALETTE; //|SDL_FULLSCREEN; thescreen = SDL_SetVideoMode(IXSIZE, IYSIZE, 8, videoflags); if (thescreen == NULL) { fprintf(stderr, "Couldn't set display mode: %s\n", SDL_GetError()); SDL_Quit(); exit(5); } stride = thescreen->pitch; videomem = thescreen->pixels; mustlock = SDL_MUSTLOCK(thescreen); locked = 0; SDL_ShowCursor(0); } void closegfx(void) { SDL_Quit(); } int checkpressed(int code) { int *p, i; i = numpressed; p = pressedcodes; while (i--) if (*p++ == code) return 1; return 0; } int checkdown(int code) { int *p, i; i = numdown; p = downcodes; while (i--) if (*p++ == code) return 1; return 0; } int checkbutton(int button) { return buttonstate & (1 << button); } int checkbuttondown(int button) { return buttondown & (1 << button); } int anydown(void) { return numdown; } int takedown(void) { int res = 0; if (numdown) { res = *downcodes; --numdown; if (numdown) memmove(downcodes, downcodes + 1, numdown * sizeof(int)); } return res; } int firstdown(void) { return *downcodes; } #define ENDMARK 0xaabacada int sdlinoutnormal[] = { SDLK_0, '0', SDLK_1, '1', SDLK_2, '2', SDLK_3, '3', SDLK_4, '4', SDLK_5, '5', SDLK_6, '6', SDLK_7, '7', SDLK_8, '8', SDLK_9, '9', SDLK_a, 'a', SDLK_b, 'b', SDLK_c, 'c', SDLK_d, 'd', SDLK_e, 'e', SDLK_f, 'f', SDLK_g, 'g', SDLK_h, 'h', SDLK_i, 'i', SDLK_j, 'j', SDLK_k, 'k', SDLK_l, 'l', SDLK_m, 'm', SDLK_n, 'n', SDLK_o, 'o', SDLK_p, 'p', SDLK_q, 'q', SDLK_r, 'r', SDLK_s, 's', SDLK_t, 't', SDLK_u, 'u', SDLK_v, 'v', SDLK_w, 'w', SDLK_x, 'x', SDLK_y, 'y', SDLK_z, 'z', SDLK_MINUS, '-', SDLK_EQUALS, '=', SDLK_LEFTBRACKET, '[', SDLK_RIGHTBRACKET, ']', SDLK_SEMICOLON, ';', SDLK_QUOTE, '\'', SDLK_SLASH, '/', SDLK_PERIOD, '.', SDLK_COMMA, ',', SDLK_BACKQUOTE, '`', SDLK_BACKSPACE, 8, SDLK_TAB, 9, SDLK_DELETE, MYDELETE, SDLK_RETURN, 13, SDLK_F1, MYF1, SDLK_F2, MYF2, SDLK_F3, MYF3, SDLK_F4, MYF4, SDLK_F5, MYF5, SDLK_F6, MYF6, SDLK_F7, MYF7, SDLK_F8, MYF8, SDLK_F9, MYF9, SDLK_F10, MYF10, SDLK_ESCAPE, 0x1b, SDLK_LEFT, MYLEFT, SDLK_RIGHT, MYRIGHT, SDLK_UP, MYUP, SDLK_DOWN, MYDOWN, SDLK_PAGEUP, MYPAGEUP, SDLK_PAGEDOWN, MYPAGEDOWN, SDLK_SPACE, ' ', SDLK_HOME, MYHOME, SDLK_END, MYEND, SDLK_LALT, MYALTL, SDLK_RALT, MYALTR, ENDMARK}; int sdlinoutshifted[] = { SDLK_0, ')', SDLK_1, '!', SDLK_2, '@', SDLK_3, '#', SDLK_4, '$', SDLK_5, '%', SDLK_6, '^', SDLK_7, '&', SDLK_8, '*', SDLK_9, '(', SDLK_a, 'A', SDLK_b, 'B', SDLK_c, 'C', SDLK_d, 'D', SDLK_e, 'E', SDLK_f, 'F', SDLK_g, 'G', SDLK_h, 'H', SDLK_i, 'I', SDLK_j, 'J', SDLK_k, 'K', SDLK_l, 'L', SDLK_m, 'M', SDLK_n, 'N', SDLK_o, 'O', SDLK_p, 'P', SDLK_q, 'Q', SDLK_r, 'R', SDLK_s, 'S', SDLK_t, 'T', SDLK_u, 'U', SDLK_v, 'V', SDLK_w, 'W', SDLK_x, 'X', SDLK_y, 'Y', SDLK_z, 'Z', SDLK_MINUS, '_', SDLK_EQUALS, '+', SDLK_LEFTBRACKET, '{', SDLK_RIGHTBRACKET, '}', SDLK_SEMICOLON, ':', SDLK_QUOTE, '"', SDLK_SLASH, '?', SDLK_PERIOD, '>', SDLK_COMMA, '<', SDLK_BACKQUOTE, '~', SDLK_BACKSPACE, 8, SDLK_TAB, 9, SDLK_DELETE, MYDELETE, SDLK_RETURN, 13, SDLK_F1, MYF1 + MYSHIFTED, SDLK_F2, MYF2 + MYSHIFTED, SDLK_F3, MYF3 + MYSHIFTED, SDLK_F4, MYF4 + MYSHIFTED, SDLK_F5, MYF5 + MYSHIFTED, SDLK_F6, MYF6 + MYSHIFTED, SDLK_F7, MYF7 + MYSHIFTED, SDLK_F8, MYF8 + MYSHIFTED, SDLK_F9, MYF9 + MYSHIFTED, SDLK_F10, MYF10 + MYSHIFTED, SDLK_ESCAPE, 0x1b, SDLK_LEFT, MYLEFT + MYSHIFTED, SDLK_RIGHT, MYRIGHT + MYSHIFTED, SDLK_UP, MYUP + MYSHIFTED, SDLK_DOWN, MYDOWN + MYSHIFTED, SDLK_PAGEUP, MYPAGEUP, SDLK_PAGEDOWN, MYPAGEDOWN, SDLK_SPACE, ' ', SDLK_HOME, MYHOME, SDLK_END, MYEND, SDLK_LALT, MYALTL, SDLK_RALT, MYALTR, ENDMARK}; static int looklist(int code, int* list) { while ((unsigned int) *list != ENDMARK) { if (*list == code) return list[1]; list += 2; } return -1; } static int mapkey(int code, int qual) { if (qual & KMOD_SHIFT) code = looklist(code, sdlinoutshifted); else code = looklist(code, sdlinoutnormal); if (code < 0) return -1; if (qual & KMOD_ALT) code |= MYALTED; return code; } static void markkey(int code, int status) { int i; int* ip; if (status) { if (numdown < KEYMAX) downcodes[numdown++] = code; ip = pressedcodes; i = numpressed; while (i) if (*ip++ == code) break; else i--; if (!i && numpressed < KEYMAX) pressedcodes[numpressed++] = code; } else { i = numpressed; ip = pressedcodes; while (i) if (*ip++ == code) { *--ip = pressedcodes[--numpressed]; break; } else i--; } } void pollinput(void) { SDL_PollEvent(0); } void scaninput(void) { SDL_Event event; int key, mod; static int bs = 0; numdown = 0; buttondown = 0; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: key = event.key.keysym.sym; mod = event.key.keysym.mod; markkey(mapkey(key, mod), 1); break; case SDL_KEYUP: key = event.key.keysym.sym; mod = event.key.keysym.mod; markkey(mapkey(key, mod), 0); break; case SDL_MOUSEBUTTONUP: bs &= ~(1 << (event.button.button - 1)); mousex = event.button.x >> 1; mousey = event.button.y >> 1; mouseb = bs; break; case SDL_MOUSEBUTTONDOWN: bs |= 1 << (event.button.button - 1); mousex = event.button.x >> 1; mousey = event.button.y >> 1; mouseb = bs; break; case SDL_MOUSEMOTION: mousex = event.motion.x >> 1; mousey = event.motion.y >> 1; break; case SDL_QUIT: exitflag = 1; break; } } } /* void scaninput() { int i,*ip,code; numdown=0; buttondown=0; while(XCheckMaskEvent(dp,~0,&event)) switch(event.type) { case KeyPress: code=XLookupKeysym(keyevent,0); if(numdownbutton; buttonstate|=i; buttondown|=i; break; case ButtonRelease: buttonstate&=~(1<button); break; case MotionNotify: mxpos=motionevent->x; mypos=motionevent->y; break; case Expose: copyup(); needwhole=0; break; case FocusOut: numpressed=0; break; } } */ static void drawrect(int x, int y, int xs, int ys, int c) { uchar* p; gfxlock(); p = videomem + y * stride + x; while (ys--) { memset(p, c, xs); p += stride; } } void greyrect(int x, int y, int xsize, int ysize) { static int greycolor = -1; if (greycolor == -1) greycolor = bestmatch(0, 0, 0x70); drawrect(x, y, xsize, ysize, greycolor); } void clear() { int j; uchar* p; gfxlock(); p = videomem; for (j = 0; j < IYSIZE; ++j) { memset(p, 0, IXSIZE); p += stride; } } void clearrect(int x, int y, int xsize, int ysize) { drawrect(x, y, xsize, ysize, 0); } void gfxlock(void) { if (locked || !mustlock) return; if (SDL_LockSurface(thescreen) < 0) { fprintf(stderr, "Couldn't lock display surface: %s\n", SDL_GetError()); } locked = 1; } void gfxunlock(void) { if (!locked || !mustlock) return; SDL_UnlockSurface(thescreen); locked = 0; }