home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / goattracker_2.68.zip / src / bme / bme_gfx.c < prev    next >
C/C++ Source or Header  |  2008-04-01  |  14KB  |  566 lines

  1. //
  2. // BME (Blasphemous Multimedia Engine) graphics main module
  3. //
  4.  
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <SDL/SDL.h>
  9.  
  10. #include "bme_main.h"
  11. #include "bme_cfg.h"
  12. #include "bme_win.h"
  13. #include "bme_io.h"
  14. #include "bme_err.h"
  15.  
  16. // Prototypes
  17.  
  18. int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags);
  19. int gfx_reinit(void);
  20. void gfx_uninit(void);
  21. int gfx_lock(void);
  22. void gfx_unlock(void);
  23. void gfx_flip(void);
  24. void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom);
  25. void gfx_setmaxspritefiles(int num);
  26. void gfx_setmaxcolors(int num);
  27. int gfx_loadpalette(char *name);
  28. void gfx_calcpalette(int fade, int radd, int gadd, int badd);
  29. void gfx_setpalette(void);
  30. int gfx_loadblocks(char *name);
  31. int gfx_loadsprites(int num, char *name);
  32. void gfx_freesprites(int num);
  33.  
  34. void gfx_drawsprite(int x, int y, unsigned num);
  35. void gfx_getspriteinfo(unsigned num);
  36.  
  37. int gfx_initted = 0;
  38. int gfx_redraw = 0;
  39. int gfx_fullscreen = 0;
  40. int gfx_scanlinemode = 0;
  41. int gfx_preventswitch = 0;
  42. int gfx_virtualxsize;
  43. int gfx_virtualysize;
  44. int gfx_windowxsize;
  45. int gfx_windowysize;
  46. int gfx_blockxsize = 16;
  47. int gfx_blockysize = 16;
  48. int spr_xsize = 0;
  49. int spr_ysize = 0;
  50. int spr_xhotspot = 0;
  51. int spr_yhotspot = 0;
  52. unsigned gfx_nblocks = 0;
  53. Uint8 gfx_palette[MAX_COLORS * 3] = {0};
  54. SDL_Surface *gfx_screen = NULL;
  55.  
  56. // Static variables
  57.  
  58. static int gfx_initexec = 0;
  59. static unsigned gfx_last_xsize;
  60. static unsigned gfx_last_ysize;
  61. static unsigned gfx_last_framerate;
  62. static unsigned gfx_last_flags;
  63. static int gfx_cliptop;
  64. static int gfx_clipbottom;
  65. static int gfx_clipleft;
  66. static int gfx_clipright;
  67. static int gfx_maxcolors = MAX_COLORS;
  68. static int gfx_maxspritefiles = 0;
  69. static SPRITEHEADER **gfx_spriteheaders = NULL;
  70. static Uint8 **gfx_spritedata = NULL;
  71. static unsigned *gfx_spriteamount = NULL;
  72. static SDL_Color gfx_sdlpalette[MAX_COLORS];
  73. static int gfx_locked = 0;
  74.  
  75. int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags)
  76. {
  77.     int sdlflags = SDL_HWSURFACE;
  78.  
  79.     // Prevent re-entry (by window procedure)
  80.     if (gfx_initexec) return BME_OK;
  81.     gfx_initexec = 1;
  82.  
  83.     gfx_last_xsize = xsize;
  84.     gfx_last_ysize = ysize;
  85.     gfx_last_framerate = framerate;
  86.     gfx_last_flags = flags & ~(GFX_FULLSCREEN | GFX_WINDOW);
  87.  
  88.     // Store the options contained in the flags
  89.  
  90.     gfx_scanlinemode = flags & (GFX_SCANLINES | GFX_DOUBLESIZE);
  91.  
  92.     if (flags & GFX_NOSWITCHING) gfx_preventswitch = 1;
  93.         else gfx_preventswitch = 0;
  94.     if (win_fullscreen) sdlflags |= SDL_FULLSCREEN;
  95.     if (flags & GFX_FULLSCREEN) sdlflags |= SDL_FULLSCREEN;
  96.     if (flags & GFX_WINDOW) sdlflags &= ~SDL_FULLSCREEN;
  97.     if (sdlflags & SDL_FULLSCREEN) gfx_fullscreen = 1;
  98.         else gfx_fullscreen = 0;
  99.  
  100.     // Calculate virtual window size
  101.  
  102.     gfx_virtualxsize = xsize;
  103.     gfx_virtualxsize /= 16;
  104.     gfx_virtualxsize *= 16;
  105.     gfx_virtualysize = ysize;
  106.  
  107.     if ((!gfx_virtualxsize) || (!gfx_virtualysize))
  108.     {
  109.         gfx_initexec = 0;
  110.         gfx_uninit();
  111.         bme_error = BME_ILLEGAL_CONFIG;
  112.         return BME_ERROR;
  113.     }
  114.  
  115.     // Calculate actual window size (for scanline mode & doublesize mode
  116.     // this is double the virtual)
  117.  
  118.     gfx_windowxsize = gfx_virtualxsize;
  119.     gfx_windowysize = gfx_virtualysize;
  120.     if (gfx_scanlinemode)
  121.     {
  122.         gfx_windowxsize <<= 1;
  123.         gfx_windowysize <<= 1;
  124.     }
  125.  
  126.     gfx_setclipregion(0, 0, gfx_virtualxsize, gfx_virtualysize);
  127.  
  128.     // Colors 0 & 255 are always black & white
  129.     gfx_sdlpalette[0].r = 0;
  130.     gfx_sdlpalette[0].g = 0;
  131.     gfx_sdlpalette[0].b = 0;
  132.     gfx_sdlpalette[255].r = 255;
  133.     gfx_sdlpalette[255].g = 255;
  134.     gfx_sdlpalette[255].b = 255;
  135.  
  136.     gfx_screen = SDL_SetVideoMode(gfx_windowxsize, gfx_windowysize, 8, sdlflags);
  137.     gfx_initexec = 0;
  138.     if (gfx_screen)
  139.     {
  140.         gfx_initted = 1;
  141.         gfx_redraw = 1;
  142.         gfx_setpalette();
  143.         win_setmousemode(win_mousemode);
  144.         return BME_OK;
  145.     }
  146.     else return BME_ERROR;
  147. }
  148.  
  149. int gfx_reinit(void)
  150. {
  151.     return gfx_init(gfx_last_xsize, gfx_last_ysize, gfx_last_framerate,
  152.         gfx_last_flags);
  153. }
  154.  
  155. void gfx_uninit(void)
  156. {
  157.     gfx_initted = 0;
  158.     return;
  159. }
  160.  
  161. int gfx_lock(void)
  162. {
  163.     if (gfx_locked) return 1;
  164.     if (!gfx_initted) return 0;
  165.     if (!SDL_LockSurface(gfx_screen))
  166.     {
  167.         gfx_locked = 1;
  168.         return 1;
  169.     }
  170.     else return 0;
  171. }
  172.  
  173. void gfx_unlock(void)
  174. {
  175.     if (gfx_locked)
  176.     {
  177.         SDL_UnlockSurface(gfx_screen);
  178.         gfx_locked = 0;
  179.     }
  180. }
  181.  
  182. void gfx_flip()
  183. {
  184.     SDL_Flip(gfx_screen);
  185.     gfx_redraw = 0;
  186. }
  187.  
  188. void gfx_setmaxcolors(int num)
  189. {
  190.     gfx_maxcolors = num;
  191. }
  192.  
  193. int gfx_loadpalette(char *name)
  194. {
  195.     int handle;
  196.  
  197.     handle = io_open(name);
  198.     if (handle == -1)
  199.     {
  200.         bme_error = BME_OPEN_ERROR;
  201.         return BME_ERROR;
  202.     }
  203.     if (io_read(handle, gfx_palette, sizeof gfx_palette) != sizeof gfx_palette)
  204.     {
  205.         bme_error = BME_READ_ERROR;
  206.         io_close(handle);
  207.         return BME_ERROR;
  208.     }
  209.  
  210.     io_close(handle);
  211.     gfx_calcpalette(64, 0, 0, 0);
  212.     bme_error = BME_OK;
  213.     return BME_OK;
  214. }
  215.  
  216. void gfx_calcpalette(int fade, int radd, int gadd, int badd)
  217. {
  218.     Uint8  *sptr = &gfx_palette[3];
  219.     int c, cl;
  220.     if (radd < 0) radd = 0;
  221.     if (gadd < 0) gadd = 0;
  222.     if (badd < 0) badd = 0;
  223.  
  224.     for (c = 1; c < 255; c++)
  225.     {
  226.         cl = *sptr;
  227.         cl *= fade;
  228.         cl >>= 6;
  229.         cl += radd;
  230.         if (cl > 63) cl = 63;
  231.         if (cl < 0) cl = 0;
  232.         gfx_sdlpalette[c].r = (cl << 2) | (cl & 3);
  233.         sptr++;
  234.  
  235.         cl = *sptr;
  236.         cl *= fade;
  237.         cl >>= 6;
  238.         cl += gadd;
  239.         if (cl > 63) cl = 63;
  240.         if (cl < 0) cl = 0;
  241.         gfx_sdlpalette[c].g = (cl << 2) | (cl & 3);
  242.         sptr++;
  243.  
  244.         cl = *sptr;
  245.         cl *= fade;
  246.         cl >>= 6;
  247.         cl += badd;
  248.         if (cl > 63) cl = 63;
  249.         if (cl < 0) cl = 0;
  250.         gfx_sdlpalette[c].b = (cl << 2) | (cl & 3);
  251.         sptr++;
  252.     }
  253. }
  254.  
  255. void gfx_setpalette(void)
  256. {
  257.     if (!gfx_initted) return;
  258.  
  259.     SDL_SetColors(gfx_screen, &gfx_sdlpalette[0], 0, gfx_maxcolors);
  260. }
  261.  
  262. void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom)
  263. {
  264.     if (left >= right) return;
  265.     if (top >= bottom) return;
  266.     if (left >= gfx_virtualxsize) return;
  267.     if (top >= gfx_virtualysize) return;
  268.     if (right > gfx_virtualxsize) return;
  269.     if (bottom > gfx_virtualysize) return;
  270.  
  271.     gfx_clipleft = left;
  272.     gfx_clipright = right;
  273.     gfx_cliptop = top;
  274.     gfx_clipbottom = bottom;
  275. }
  276.  
  277. void gfx_setmaxspritefiles(int num)
  278. {
  279.     if (num <= 0) return;
  280.  
  281.     if (gfx_spriteheaders) return;
  282.  
  283.     gfx_spriteheaders = malloc(num * sizeof(Uint8 *));
  284.     gfx_spritedata = malloc(num * sizeof(Uint8 *));
  285.     gfx_spriteamount = malloc(num * sizeof(unsigned));
  286.     if ((gfx_spriteheaders) && (gfx_spritedata) && (gfx_spriteamount))
  287.     {
  288.         int c;
  289.  
  290.         gfx_maxspritefiles = num;
  291.         for (c = 0; c < num; c++)
  292.         {
  293.             gfx_spriteamount[c] = 0;
  294.             gfx_spritedata[c] = NULL;
  295.             gfx_spriteheaders[c] = NULL;
  296.         }
  297.     }
  298.     else gfx_maxspritefiles = 0;
  299. }
  300.  
  301. int gfx_loadsprites(int num, char *name)
  302. {
  303.     int handle, size, c;
  304.     int datastart;
  305.  
  306.     if (!gfx_spriteheaders)
  307.     {
  308.         gfx_setmaxspritefiles(DEFAULT_MAX_SPRFILES);
  309.     }
  310.  
  311.     bme_error = BME_OPEN_ERROR;
  312.     if (num >= gfx_maxspritefiles) return BME_ERROR;
  313.  
  314.     gfx_freesprites(num);
  315.  
  316.     handle = io_open(name);
  317.     if (handle == -1) return BME_ERROR;
  318.  
  319.     size = io_lseek(handle, 0, SEEK_END);
  320.     io_lseek(handle, 0, SEEK_SET);
  321.  
  322.     gfx_spriteamount[num] = io_readle32(handle);
  323.  
  324.     gfx_spriteheaders[num] = malloc(gfx_spriteamount[num] * sizeof(SPRITEHEADER));
  325.  
  326.     if (!gfx_spriteheaders[num])
  327.     {
  328.         bme_error = BME_OUT_OF_MEMORY;    
  329.         io_close(handle);
  330.         return BME_ERROR;
  331.     }
  332.  
  333.     for (c = 0; c < gfx_spriteamount[num]; c++)
  334.     {
  335.         SPRITEHEADER *hptr = gfx_spriteheaders[num] + c;
  336.  
  337.         hptr->xsize = io_readle16(handle);
  338.         hptr->ysize = io_readle16(handle);
  339.         hptr->xhot = io_readle16(handle);
  340.         hptr->yhot = io_readle16(handle);
  341.         hptr->offset = io_readle32(handle);
  342.     }
  343.  
  344.     datastart = io_lseek(handle, 0, SEEK_CUR);
  345.     gfx_spritedata[num] = malloc(size - datastart);
  346.     if (!gfx_spritedata[num])
  347.     {
  348.         bme_error = BME_OUT_OF_MEMORY;    
  349.         io_close(handle);
  350.         return BME_ERROR;
  351.     }
  352.     io_read(handle, gfx_spritedata[num], size - datastart);
  353.     io_close(handle);
  354.     bme_error = BME_OK;
  355.     return BME_OK;
  356. }
  357.  
  358. void gfx_freesprites(int num)
  359. {
  360.     if (num >= gfx_maxspritefiles) return;
  361.  
  362.     if (gfx_spritedata[num])
  363.     {
  364.         free(gfx_spritedata[num]);
  365.         gfx_spritedata[num] = NULL;
  366.     }
  367.     if (gfx_spriteheaders[num])
  368.     {
  369.         free(gfx_spriteheaders[num]);
  370.         gfx_spriteheaders[num] = NULL;
  371.     }
  372. }
  373.  
  374. void gfx_copyscreen8(Uint8  *destaddress, Uint8  *srcaddress, unsigned pitch)
  375. {
  376.     int c, d;
  377.  
  378.     switch(gfx_scanlinemode)
  379.     {
  380.         default:
  381.         for (c = 0; c < gfx_virtualysize; c++)
  382.         {
  383.             memcpy(destaddress, srcaddress, gfx_virtualxsize);
  384.             destaddress += pitch;
  385.             srcaddress += gfx_virtualxsize;
  386.         }
  387.         break;
  388.  
  389.         case GFX_SCANLINES:
  390.         for (c = 0; c < gfx_virtualysize; c++)
  391.         {
  392.             d = gfx_virtualxsize;
  393.             while (d--)
  394.             {
  395.                 *destaddress = *srcaddress;
  396.                 destaddress++;
  397.                 *destaddress = *srcaddress;
  398.                 destaddress++;
  399.                 srcaddress++;
  400.             }
  401.             destaddress += pitch*2 - (gfx_virtualxsize << 1);
  402.         }
  403.         break;
  404.  
  405.         case GFX_DOUBLESIZE:
  406.         for (c = 0; c < gfx_virtualysize; c++)
  407.         {
  408.             d = gfx_virtualxsize;
  409.             while (d--)
  410.             {
  411.                 *destaddress = *srcaddress;
  412.                 destaddress++;
  413.                 *destaddress = *srcaddress;
  414.                 destaddress++;
  415.                 srcaddress++;
  416.             }
  417.             destaddress += pitch - (gfx_virtualxsize << 1);
  418.             srcaddress -= gfx_virtualxsize;
  419.             d = gfx_virtualxsize;
  420.             while (d--)
  421.             {
  422.                 *destaddress = *srcaddress;
  423.                 destaddress++;
  424.                 *destaddress = *srcaddress;
  425.                 destaddress++;
  426.                 srcaddress++;
  427.             }
  428.             destaddress += pitch - (gfx_virtualxsize << 1);
  429.         }
  430.         break;
  431.     }
  432. }
  433.  
  434.  
  435. void gfx_getspriteinfo(unsigned num)
  436. {
  437.     unsigned sprf = num >> 16;
  438.     unsigned spr = (num & 0xffff) - 1;
  439.     SPRITEHEADER *hptr;
  440.  
  441.     if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) ||
  442.         (spr >= gfx_spriteamount[sprf])) hptr = NULL;
  443.     else hptr = gfx_spriteheaders[sprf] + spr;
  444.  
  445.     if (!hptr)
  446.     {
  447.         spr_xsize = 0;
  448.         spr_ysize = 0;
  449.         spr_xhotspot = 0;
  450.         spr_yhotspot = 0;
  451.         return;
  452.     }
  453.  
  454.     spr_xsize = hptr->xsize;
  455.     spr_ysize = hptr->ysize;
  456.     spr_xhotspot = hptr->xhot;
  457.     spr_yhotspot = hptr->yhot;
  458. }
  459.  
  460. void gfx_drawsprite(int x, int y, unsigned num)
  461. {
  462.     unsigned sprf = num >> 16;
  463.     unsigned spr = (num & 0xffff) - 1;
  464.     SPRITEHEADER *hptr;
  465.  
  466.     if (!gfx_initted) return;
  467.     if (!gfx_locked) return;
  468.  
  469.     Uint8 *sptr;
  470.     Uint8 *dptr;
  471.     int cx;
  472.  
  473.     if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) ||
  474.         (spr >= gfx_spriteamount[sprf]))
  475.     {
  476.         spr_xsize = 0;
  477.         spr_ysize = 0;
  478.         spr_xhotspot = 0;
  479.         spr_yhotspot = 0;
  480.         return;
  481.     }
  482.     else hptr = gfx_spriteheaders[sprf] + spr;
  483.  
  484.     sptr = gfx_spritedata[sprf] + hptr->offset;
  485.     spr_xsize = hptr->xsize;
  486.     spr_ysize = hptr->ysize;
  487.     spr_xhotspot = hptr->xhot;
  488.     spr_yhotspot = hptr->yhot;
  489.  
  490.     x -= spr_xhotspot;
  491.     y -= spr_yhotspot;
  492.  
  493.     if (x >= gfx_clipright) return;
  494.     if (y >= gfx_clipbottom) return;
  495.     if (x + spr_xsize <= gfx_clipleft) return;
  496.     if (y + spr_ysize <= gfx_cliptop) return;
  497.  
  498.     while (y < gfx_cliptop)
  499.     {
  500.         int dec = *sptr++;
  501.         if (dec == 255)
  502.         {
  503.             if (!(*sptr)) return;
  504.             y++;
  505.         }
  506.         else
  507.         {
  508.             if (dec < 128)
  509.             {
  510.                 sptr += dec;
  511.             }
  512.         }
  513.     }
  514.     while (y < gfx_clipbottom)
  515.     {
  516.         int dec;
  517.         cx = x;
  518.         dptr = gfx_screen->pixels + y * gfx_screen->pitch + x;
  519.  
  520.         for (;;)
  521.         {
  522.             dec = *sptr++;
  523.  
  524.             if (dec == 255)
  525.             {
  526.                 if (!(*sptr)) return;
  527.                 y++;
  528.                 break;
  529.             }
  530.             if (dec < 128)
  531.             {
  532.                 if ((cx + dec <= gfx_clipleft) || (cx >= gfx_clipright))
  533.                 {
  534.                     goto SKIP;
  535.                 }
  536.                 if (cx < gfx_clipleft)
  537.                 {
  538.                     dec -= (gfx_clipleft - cx);
  539.                     sptr += (gfx_clipleft - cx);
  540.                     dptr += (gfx_clipleft - cx);
  541.                     cx = gfx_clipleft;
  542.                 }
  543.                 while ((cx < gfx_clipright) && (dec))
  544.                 {
  545.                     *dptr = *sptr;
  546.                     cx++;
  547.                     sptr++;
  548.                     dptr++;
  549.                     dec--;
  550.                 }
  551.                 SKIP:
  552.                 cx += dec;
  553.                 sptr += dec;
  554.                 dptr += dec;
  555.             }
  556.             else
  557.             {
  558.                 cx += (dec & 0x7f);
  559.                 dptr += (dec & 0x7f);
  560.             }
  561.         }
  562.     }
  563. }
  564.  
  565.  
  566.