svgal_vd.cc 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #include "video/display.hh"
  9. #include "video/svgalib/svgal_vd.hh"
  10. #include "image/image8.hh"
  11. #include "device/kernel.hh"
  12. #include <string.h>
  13. #include <vga.h>
  14. #include <unistd.h>
  15. svgalib_display_class svgalib_display_instance;
  16. svgalib_display_class::svgalib_display_class()
  17. {
  18. init=NOT_INITIALIZED;
  19. screen=NULL;
  20. mouse_notify.display=this;
  21. mouse_event_flags=0;
  22. mouse_pict=mouse_save=NULL;
  23. context=0;
  24. }
  25. svgalib_display_class::~svgalib_display_class()
  26. {
  27. kernel.remove_device(&devs);
  28. }
  29. i4_image_class *svgalib_display_class::next_frame_screen(i4_rect_list_class *area_of_change)
  30. {
  31. i4_rect_list_class::area *a=area_of_change->get_list();
  32. for (;a;a=a->next) // add all of the area of change to the dirty list
  33. screen->dirty.add_area(a->x1,a->y1,a->x2,a->y2);
  34. return screen;
  35. }
  36. i4_image_class *svgalib_display_class::both_screens()
  37. {
  38. return screen;
  39. }
  40. void svgalib_display_class::flush()
  41. {
  42. int mw,mh;
  43. i4_rect_list_class no_clip(0,0,width()-1,height()-1);
  44. if (mouse_pict)
  45. {
  46. screen->clip_list.swap(&no_clip);
  47. mw=mouse_pict->width();
  48. mh=mouse_pict->height();
  49. mouse_save->set_pal(pal);
  50. mouse_save->copy_part(screen,0,0,mouse_x,mouse_y,mouse_x+mw-1,mouse_y+mh-1); // save area behind mouse
  51. screen->copy_from_trans(mouse_pict,mouse_x,mouse_y,0);
  52. }
  53. i4_rect_list_class::area *a=screen->dirty.get_list(),*next;
  54. for (;a;a=next)
  55. {
  56. next=a->next;
  57. copy_part_to_vram(screen,a->x1,a->y1,a->x1,a->y1,a->x2,a->y2);
  58. }
  59. screen->dirty.delete_list();
  60. if (mouse_pict)
  61. {
  62. screen->copy_part(mouse_save,mouse_x,mouse_y,0,0,mw-1,mh-1); // restore area behind mouse
  63. screen->clip_list.swap(&no_clip);
  64. }
  65. }
  66. void svgalib_display_class::copy_part_to_vram(i4_image_class *im, int x, int y, int x1, int y1, int x2, int y2)
  67. {
  68. unsigned long screen_off;
  69. int ys,ye, // ystart, yend
  70. xs,xe,
  71. page,last_page=-1,yy;
  72. long breaker;
  73. unsigned char *line_addr;
  74. int xres=width()-1,yres=height()-1;
  75. if (y>(int)yres || x>(int)xres) return ;
  76. if (y<0)
  77. { y1+=-y; y=0; }
  78. ys=y1;
  79. if (y+(y2-y1)>=(int)yres)
  80. ye=(int)yres-y+y1-1;
  81. else ye=y2;
  82. if (x<0)
  83. { x1+=-x; x=0; }
  84. xs=x1;
  85. if (x+(x2-x1)>=(int)xres)
  86. xe=(int)xres-x+x1-1;
  87. else xe=x2;
  88. if (xs>xe || ys>ye) return ;
  89. // find the memory offset for the scan line of interest
  90. screen_off=((long)y*(long)(xres+1));
  91. int bpl=screen->bytes_per_line();
  92. for (yy=ys;yy<=ye;yy++,screen_off+=(xres+1))
  93. {
  94. page=screen_off>>16; // which page of 64k are we on?
  95. if (page!=last_page)
  96. { last_page=page;
  97. vga_setpage(page); // switch to new bank
  98. }
  99. line_addr=im->image_data()+yy*bpl+xs;
  100. // breaker is the number of bytes before the page split
  101. breaker=(long)0xffff-(long)(screen_off&0xffff)+1;
  102. // see if the slam gets split by the page break
  103. if (breaker>x+xe-xs)
  104. {
  105. void *dest=v_addr+(screen_off&0xffff)+x;
  106. int size=xe-xs+1;
  107. memcpy(dest,line_addr,size);
  108. }
  109. else if (breaker<=x)
  110. { last_page++;
  111. vga_setpage(last_page);
  112. memcpy(v_addr+x-breaker,line_addr,xe-xs+1);
  113. }
  114. else
  115. {
  116. memcpy(v_addr+(screen_off&0xffff)+x,line_addr,breaker-x);
  117. last_page++;
  118. vga_setpage(last_page);
  119. memcpy(v_addr,line_addr+breaker-x,xe-xs-(breaker-x)+1);
  120. }
  121. y++;
  122. }
  123. }
  124. static int svga_modes[]={ // a list of a the SVGALIB supported modes we support
  125. G320x200x256,
  126. /* G320x240x256, // modex only?
  127. G320x400x256,
  128. G360x480x256, */
  129. G640x480x256,
  130. G800x600x256,
  131. G1024x768x256,
  132. G1280x1024x256,
  133. -1
  134. } ;
  135. void svgalib_display_class::fill_amode(int mode)
  136. {
  137. memset(&amode,0,sizeof(amode));
  138. amode.mode_num=mode;
  139. vga_modeinfo *m=vga_getmodeinfo(svga_modes[mode]);
  140. amode.bits_per_pixel=8;
  141. amode.bits_per_color=8;
  142. amode.assoc=this;
  143. amode.xres=m->width;
  144. amode.yres=m->height;
  145. }
  146. i4_display_class::mode *svgalib_display_class::get_first_mode()
  147. {
  148. if (!available()) return NULL;
  149. fill_amode(0);
  150. return &amode;
  151. }
  152. i4_display_class::mode *svgalib_display_class::get_next_mode(mode *last_mode)
  153. {
  154. if (!last_mode || ((svga_mode *)last_mode)->assoc!=this) return NULL; // make sure we created the last mode
  155. if (svga_modes[((svga_mode *)last_mode)->mode_num+1]==-1) return NULL; // any mode modes left?
  156. fill_amode( ((svga_mode *)last_mode)->mode_num+1);
  157. return &amode;
  158. }
  159. static unsigned char def_mouse[]=
  160. { 0,2,0,0,0,0,0,0,
  161. 2,1,2,0,0,0,0,0,
  162. 2,1,1,2,0,0,0,0,
  163. 2,1,1,1,2,0,0,0,
  164. 2,1,1,1,1,2,0,0,
  165. 2,1,1,1,1,1,2,0,
  166. 0,2,1,1,2,2,0,0,
  167. 0,0,2,1,1,2,0,0,
  168. 0,0,2,1,1,2,0,0,
  169. 0,0,0,2,2,0,0,0 }; // 8x10
  170. // initialize_mode need not call close() to switch to another mode
  171. i4_bool svgalib_display_class::initialize_mode(mode *which_one)
  172. {
  173. if (!which_one || ((svga_mode *)which_one)->assoc!=this) return i4_F;
  174. cur_svga_mode=svga_modes[((svga_mode *)which_one)->mode_num];
  175. vga_setmode(cur_svga_mode);
  176. v_addr=vga_getgraphmem();
  177. if (pal.is_32bit()) // palette has not been created yet
  178. {
  179. w32 initial_pal[256];
  180. int x;
  181. for (x=0;x<256;x++) // initialize to a gray scale pal
  182. initial_pal[x]=(x<<16)|(x<<8)|x;
  183. pal=i4_pal_man.register_pal(i4_pal_handle_class::ID_8BIT,initial_pal);
  184. }
  185. realize_palette(pal);
  186. if (screen)
  187. delete screen;
  188. screen=new i4_image8_clippable(which_one->xres,which_one->yres,pal);
  189. if (mouse_pal.is_32bit())
  190. {
  191. w32 mpal[256];
  192. memset(mpal,0,sizeof(mpal));
  193. mpal[0]=0;
  194. mpal[1]=0xffffff;
  195. mpal[2]=0x080808;
  196. mouse_pal=i4_pal_man.register_pal(i4_pal_handle_class::ID_8BIT,mpal);
  197. }
  198. if (!mouse_event_flags)
  199. mouse_event_flags=local_devices()->request_device(&mouse_notify,i4_device_class::FLAG_MOUSE_MOVE);
  200. if (mouse_pict) // has the mouse already been initialized?
  201. {
  202. delete mouse_pict; mouse_pict=NULL;
  203. delete mouse_save; mouse_save=NULL;
  204. }
  205. if (mouse_event_flags)
  206. {
  207. mouse_pict=new i4_image8(8,10,mouse_pal); // the mouse pict has it's own palette to ensure it will be displayed properly
  208. mouse_save=new i4_image8(8,10,pal); // the save image (for behinf the mouse) uses the screen palette
  209. memcpy(mouse_pict->image_data(),def_mouse,8*10);
  210. }
  211. }
  212. // should be called before a program quits
  213. i4_bool svgalib_display_class::close()
  214. {
  215. if (mouse_event_flags)
  216. {
  217. mouse_event_flags=0;
  218. local_devices()->release_device(&mouse_notify,i4_device_class::FLAG_MOUSE_MOVE);
  219. }
  220. if (screen)
  221. {
  222. delete screen;
  223. screen=NULL;
  224. }
  225. if (mouse_pict)
  226. {
  227. delete mouse_pict;
  228. mouse_pict=NULL;
  229. }
  230. if (mouse_save)
  231. {
  232. delete mouse_save;
  233. mouse_save=NULL;
  234. }
  235. vga_setmode(TEXT);
  236. }
  237. i4_bool svgalib_display_class::available()
  238. {
  239. if (init==NOT_INITIALIZED)
  240. {
  241. if (ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1)!=0) // make sure we have permission to vga ports
  242. init=INITIALIZED_AND_NOT_AVAILABLE;
  243. else if (vga_init()==-1)
  244. init=INITIALIZED_AND_NOT_AVAILABLE;
  245. else
  246. init=INITIALIZED_AND_AVAILABLE;
  247. }
  248. return (i4_bool)(init==INITIALIZED_AND_AVAILABLE);
  249. }
  250. i4_bool svgalib_display_class::realize_palette(i4_pal_handle_class pal_id)
  251. {
  252. if (pal_id.is_8bit())
  253. {
  254. w32 *data=i4_pal_man.get_pal(pal_id);
  255. for (int i=0;i<256;i++,data++)
  256. vga_setpalette(i,(((*data)>>18)&0x3f),
  257. (((*data)>>10)&0x3f),
  258. (((*data)>>2)&0x3f));
  259. pal=pal_id;
  260. if (screen)
  261. screen->set_pal(pal);
  262. return i4_T;
  263. } else return i4_F;
  264. }