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 |
|
---|
18 | svgalib_display_class svgalib_display_instance;
|
---|
19 |
|
---|
20 | svgalib_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 |
|
---|
31 | svgalib_display_class::~svgalib_display_class()
|
---|
32 | {
|
---|
33 | kernel.remove_device(&devs);
|
---|
34 | }
|
---|
35 |
|
---|
36 |
|
---|
37 | i4_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 |
|
---|
48 | i4_image_class *svgalib_display_class::both_screens()
|
---|
49 | {
|
---|
50 | return screen;
|
---|
51 | }
|
---|
52 |
|
---|
53 | void 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 |
|
---|
86 | void 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 |
|
---|
157 | static 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 |
|
---|
170 | void 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 |
|
---|
183 | i4_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 |
|
---|
192 | i4_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 |
|
---|
201 | static 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
|
---|
216 | i4_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
|
---|
272 | i4_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 |
|
---|
304 | i4_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 |
|
---|
321 | i4_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 |
|
---|