source: golgotha/src/i4/video/svgalib/svgal_vd.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 14 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 8.1 KB
Line 
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
9#include "video/display.hh"
10#include "video/svgalib/svgal_vd.hh"
11#include "image/image8.hh"
12#include "device/kernel.hh"
13
14#include <string.h>
15#include <vga.h>
16#include <unistd.h>
17
18svgalib_display_class svgalib_display_instance;
19
20svgalib_display_class::svgalib_display_class()
21{
22  init=NOT_INITIALIZED;
23  screen=NULL;
24  mouse_notify.display=this;
25
26  mouse_event_flags=0;
27  mouse_pict=mouse_save=NULL;
28  context=0;
29}
30
31svgalib_display_class::~svgalib_display_class()
32{
33  kernel.remove_device(&devs);
34}
35
36
37i4_image_class *svgalib_display_class::next_frame_screen(i4_rect_list_class *area_of_change)
38{
39  i4_rect_list_class::area *a=area_of_change->get_list();
40 
41  for (;a;a=a->next)   // add all of the area of change to the dirty list
42    screen->dirty.add_area(a->x1,a->y1,a->x2,a->y2);
43
44  return screen;
45}
46
47
48i4_image_class *svgalib_display_class::both_screens()
49{
50  return screen;
51}
52
53void svgalib_display_class::flush()
54{
55  int mw,mh;
56  i4_rect_list_class no_clip(0,0,width()-1,height()-1);
57
58  if (mouse_pict)
59  {
60    screen->clip_list.swap(&no_clip);
61
62    mw=mouse_pict->width();
63    mh=mouse_pict->height();
64    mouse_save->set_pal(pal);
65
66    mouse_save->copy_part(screen,0,0,mouse_x,mouse_y,mouse_x+mw-1,mouse_y+mh-1);  // save area behind mouse
67    screen->copy_from_trans(mouse_pict,mouse_x,mouse_y,0);
68  }
69
70  i4_rect_list_class::area *a=screen->dirty.get_list(),*next;
71  for (;a;a=next)
72  {
73    next=a->next;
74    copy_part_to_vram(screen,a->x1,a->y1,a->x1,a->y1,a->x2,a->y2);
75  } 
76  screen->dirty.delete_list();
77
78  if (mouse_pict)
79  {   
80    screen->copy_part(mouse_save,mouse_x,mouse_y,0,0,mw-1,mh-1);   // restore area behind mouse
81    screen->clip_list.swap(&no_clip);
82  } 
83}
84
85
86void svgalib_display_class::copy_part_to_vram(i4_image_class *im, int x, int y, int x1, int y1, int x2, int y2)
87{
88  unsigned long screen_off;
89  int ys,ye,         // ystart, yend
90        xs,xe,     
91        page,last_page=-1,yy;
92  long breaker;
93  unsigned char *line_addr;
94  int xres=width()-1,yres=height()-1;
95
96  if (y>(int)yres || x>(int)xres) return ;
97
98
99  if (y<0)
100  { y1+=-y; y=0; }
101  ys=y1;
102  if (y+(y2-y1)>=(int)yres)
103    ye=(int)yres-y+y1-1;
104  else ye=y2;
105
106  if (x<0)
107  { x1+=-x; x=0; }
108  xs=x1;
109  if (x+(x2-x1)>=(int)xres)
110    xe=(int)xres-x+x1-1;
111  else xe=x2;
112  if (xs>xe || ys>ye) return ;
113
114  // find the memory offset for the scan line of interest
115  screen_off=((long)y*(long)(xres+1));
116  int bpl=screen->bytes_per_line();
117
118
119  for (yy=ys;yy<=ye;yy++,screen_off+=(xres+1))
120  {
121    page=screen_off>>16;     // which page of 64k are we on?
122    if (page!=last_page)     
123    { last_page=page;
124      vga_setpage(page);     // switch to new bank
125    }
126
127    line_addr=im->image_data()+yy*bpl+xs;
128
129    // breaker is the number of bytes before the page split
130    breaker=(long)0xffff-(long)(screen_off&0xffff)+1;
131
132
133    // see if the slam gets split by the page break
134    if (breaker>x+xe-xs)
135    {
136      void *dest=v_addr+(screen_off&0xffff)+x;
137      int size=xe-xs+1;
138      memcpy(dest,line_addr,size);
139    }
140    else if (breaker<=x)
141    { last_page++;
142      vga_setpage(last_page);
143      memcpy(v_addr+x-breaker,line_addr,xe-xs+1);
144    }
145    else
146    {
147      memcpy(v_addr+(screen_off&0xffff)+x,line_addr,breaker-x);
148      last_page++;
149      vga_setpage(last_page);
150      memcpy(v_addr,line_addr+breaker-x,xe-xs-(breaker-x)+1);
151    }
152    y++;   
153  }
154}
155
156
157static int svga_modes[]={  // a list of a the SVGALIB supported modes we support
158  G320x200x256,
159/*  G320x240x256,       // modex only?
160  G320x400x256,
161  G360x480x256, */
162  G640x480x256,
163  G800x600x256,
164  G1024x768x256,
165  G1280x1024x256,
166  -1
167} ;
168
169
170void svgalib_display_class::fill_amode(int mode)
171{
172  memset(&amode,0,sizeof(amode));
173  amode.mode_num=mode;
174  vga_modeinfo *m=vga_getmodeinfo(svga_modes[mode]);
175  amode.bits_per_pixel=8;
176  amode.bits_per_color=8;
177  amode.assoc=this;
178  amode.xres=m->width;
179  amode.yres=m->height;
180}
181
182
183i4_display_class::mode *svgalib_display_class::get_first_mode()
184{
185  if (!available()) return NULL;
186
187  fill_amode(0);
188  return &amode;
189}
190
191
192i4_display_class::mode *svgalib_display_class::get_next_mode(mode *last_mode)
193{
194  if (!last_mode || ((svga_mode *)last_mode)->assoc!=this) return NULL;   // make sure we created the last mode
195  if (svga_modes[((svga_mode *)last_mode)->mode_num+1]==-1) return NULL;     // any mode modes left?
196  fill_amode(  ((svga_mode *)last_mode)->mode_num+1);
197  return &amode;
198}
199
200
201static unsigned char def_mouse[]=
202    { 0,2,0,0,0,0,0,0,
203      2,1,2,0,0,0,0,0,
204      2,1,1,2,0,0,0,0,
205      2,1,1,1,2,0,0,0,
206
207      2,1,1,1,1,2,0,0,
208      2,1,1,1,1,1,2,0,
209      0,2,1,1,2,2,0,0,
210      0,0,2,1,1,2,0,0,
211      0,0,2,1,1,2,0,0,
212      0,0,0,2,2,0,0,0 };    // 8x10
213
214
215  // initialize_mode need not call close() to switch to another mode
216i4_bool svgalib_display_class::initialize_mode(mode *which_one)
217{
218  if (!which_one || ((svga_mode *)which_one)->assoc!=this) return i4_F;
219
220  cur_svga_mode=svga_modes[((svga_mode *)which_one)->mode_num];
221  vga_setmode(cur_svga_mode);
222
223  v_addr=vga_getgraphmem();
224  if (pal.is_32bit())          // palette has not been created yet
225  {
226    w32 initial_pal[256];
227    int x;
228    for (x=0;x<256;x++)                       // initialize to a gray scale pal
229      initial_pal[x]=(x<<16)|(x<<8)|x;
230
231    pal=i4_pal_man.register_pal(i4_pal_handle_class::ID_8BIT,initial_pal);
232  }
233
234  realize_palette(pal);
235
236  if (screen)
237    delete screen;
238
239  screen=new i4_image8_clippable(which_one->xres,which_one->yres,pal);
240
241
242  if (mouse_pal.is_32bit())
243  {
244    w32 mpal[256];
245    memset(mpal,0,sizeof(mpal));
246    mpal[0]=0;
247    mpal[1]=0xffffff;
248    mpal[2]=0x080808;
249    mouse_pal=i4_pal_man.register_pal(i4_pal_handle_class::ID_8BIT,mpal);
250  }
251
252  if (!mouse_event_flags)
253    mouse_event_flags=local_devices()->request_device(&mouse_notify,i4_device_class::FLAG_MOUSE_MOVE);
254
255  if (mouse_pict)    // has the mouse already been initialized?
256  {
257    delete mouse_pict;  mouse_pict=NULL;
258    delete mouse_save;  mouse_save=NULL;
259  }
260
261  if (mouse_event_flags)
262  {
263    mouse_pict=new i4_image8(8,10,mouse_pal);    // the mouse pict has it's own palette to ensure it will be displayed properly
264    mouse_save=new i4_image8(8,10,pal);    // the save image (for behinf the mouse) uses the screen palette
265    memcpy(mouse_pict->image_data(),def_mouse,8*10);
266  }
267
268 
269}
270
271  // should be called before a program quits
272i4_bool svgalib_display_class::close()
273{
274  if (mouse_event_flags)
275  {
276    mouse_event_flags=0;
277    local_devices()->release_device(&mouse_notify,i4_device_class::FLAG_MOUSE_MOVE);
278  }
279
280  if (screen)
281  {
282    delete screen;
283    screen=NULL;
284  }
285
286  if (mouse_pict)
287  {
288    delete mouse_pict;
289    mouse_pict=NULL;
290  }
291
292  if (mouse_save)
293  {
294    delete mouse_save;
295    mouse_save=NULL;
296  }
297
298  vga_setmode(TEXT);
299
300
301}
302
303
304i4_bool svgalib_display_class::available()
305{
306  if (init==NOT_INITIALIZED)
307  {
308    if (ioperm(0x3b4, 0x3df - 0x3b4 + 1, 1)!=0)   // make sure we have permission to vga ports
309      init=INITIALIZED_AND_NOT_AVAILABLE;
310    else if (vga_init()==-1)
311      init=INITIALIZED_AND_NOT_AVAILABLE;
312    else
313      init=INITIALIZED_AND_AVAILABLE;
314  }
315
316  return (i4_bool)(init==INITIALIZED_AND_AVAILABLE);
317}
318
319
320
321i4_bool svgalib_display_class::realize_palette(i4_pal_handle_class pal_id)
322{
323  if (pal_id.is_8bit())
324  {
325    w32 *data=i4_pal_man.get_pal(pal_id);
326    for (int i=0;i<256;i++,data++)
327      vga_setpalette(i,(((*data)>>18)&0x3f),
328                       (((*data)>>10)&0x3f),
329                       (((*data)>>2)&0x3f));
330    pal=pal_id;
331    if (screen)
332      screen->set_pal(pal);
333    return i4_T;
334  } else return i4_F;
335}
336
Note: See TracBrowser for help on using the repository browser.