gpfce patch part3
[fceu.git] / drivers / pc / svga-video.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 1998 \Firebug\
5 * Copyright (C) 2002 Ben Parnell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <stdio.h>
23#include <string.h>
24#include <vga.h>
25#include <sys/io.h>
26
27#define inportb inb
28#define outportb(port, value) outb(value, port)
29#define outportw(port, value) outw(value, port)
30
31#include "main.h"
32#include "svgalib.h"
33#include "svga-video.h"
34
35
36int vmode=1;
37
38#ifdef FRAMESKIP
39int FCEUDfskip=0;
40#endif
41
42static int vidready=0;
43static int conlock=0;
44
45void LockConsole(void)
46{
47 if(!conlock)
48 {
49 vga_lockvc();
50 conlock=1;
51 FCEUI_DispMessage("Console locked.");
52 }
53}
54
55void UnlockConsole(void)
56{
57 if(conlock)
58 {
59 vga_unlockvc();
60 conlock=0;
61 FCEUI_DispMessage("Console unlocked.");
62 }
63}
64
65void SetBorder(void)
66{
67 if(!conlock)
68 vga_lockvc();
69 inportb(0x3da);
70 outportb(0x3c0,(0x11|0x20));
71 outportb(0x3c0,0x80);
72 if(!conlock)
73 vga_unlockvc();
74}
75
76#include "vgatweak.c"
77
78void TweakVGA(int VGAMode)
79{
80 int I;
81
82 if(!conlock)
83 vga_lockvc();
84
85 outportb(0x3C8,0x00);
86 for(I=0;I<768;I++) outportb(0x3C9,0x00);
87
88 outportb(0x3D4,0x11);
89 I=inportb(0x3D5)&0x7F;
90 outportb(0x3D4,0x11);
91 outportb(0x3D5,I);
92
93 switch(VGAMode)
94 {
95 case 1: for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break;
96 case 2: for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break;
97 case 3: for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break;
98 case 6: for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break;
99 case 8: for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break;
100 default: break;
101 }
102
103 outportb(0x3da,0);
104 if(!conlock)
105 vga_unlockvc();
106}
107
108
109static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
110
111static void FlushPalette(void)
112{
113 int x;
114 for(x=0;x<256;x++)
115 {
116 int z=x;
117 if(vmode==4 || vmode==5 || vmode==7) z^=0x80;
118 vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2);
119 }
120}
121
122void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
123{
124 palettedbr[index]=r;
125 palettedbg[index]=g;
126 palettedbb[index]=b;
127
128 if(vidready)
129 {
130 if(vmode==4 || vmode==5 || vmode==7) index^=0x80;
131 vga_setpalette(index,r>>2,g>>2,b>>2);
132 }
133}
134
135
136void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b)
137{
138 *r=palettedbr[i];
139 *g=palettedbg[i];
140 *b=palettedbb[i];
141}
142
143static void vcfix(void)
144{
145 int z;
146
147 if(!conlock)
148 vga_lockvc();
149 z=inportb(0x3cc);
150 if(!conlock)
151 vga_unlockvc();
152 if(z!=0xe3 && z!=0xe7) // Common value in all tweaked video modes(and not in 320x200 mode).
153 {
154 TweakVGA(vmode);
155 SetBorder();
156 FlushPalette();
157 }
158}
159
160static uint8 *ScreenLoc;
161
162int InitVideo(void)
163{
164 #ifdef DUMMY
165 return(1);
166 #endif
167 vidready=0;
168
169 if(vmode<=3 || vmode==6 || vmode==8)
170 {
171 if(vga_getcurrentchipset()==FBDEV)
172 {
173 puts("Tweaked VGA video modes will not work. Using a 320x240 video mode instead...");
174 vmode=7;
175 }
176 }
177
178 switch(vmode)
179 {
180 default:
181 case 1:
182 case 2:
183 case 3:
184 case 6:
185 case 8:
186 vga_setmode(G320x200x256);
187 vidready|=1;
188 ScreenLoc=vga_getgraphmem();
189 TweakVGA(vmode);
190 SetBorder();
191 memset(ScreenLoc,128,256*256);
192 break;
193 case 4:
194 case 5:
195 if(!(vga_getmodeinfo(G640x480x256)->flags & CAPABLE_LINEAR))
196 {
197 puts("Video: No linear addressing mode available!");
198 return 0;
199 }
200 if(vga_setmode(G640x480x256)==-1)
201 {
202 puts("Video: Could not set 640x480x8bpp video mode!");
203 return 0;
204 }
205 vidready|=1;
206
207 vga_setpage(0);
208 if(vga_setlinearaddressing()!=-1)
209 ScreenLoc=vga_getgraphmem();
210 else
211 {
212 puts("Video: Could not set linear addressing!");
213 return 0;
214 }
215 memset(ScreenLoc,0,640*480);
216 break;
217 case 7:
218 if(!(vga_getmodeinfo(G320x240x256V)->flags & CAPABLE_LINEAR))
219 {
220 puts("Video: No linear addressing mode available!");
221 return 0;
222 }
223 if(vga_setmode(G320x240x256V)==-1)
224 {
225 puts("Video: Could not set 320x240x8bpp video mode!");
226 return 0;
227 }
228 vidready|=1;
229
230 vga_setpage(0);
231 if(vga_setlinearaddressing()!=-1)
232 ScreenLoc=vga_getgraphmem();
233 else
234 {
235 puts("Video: Could not set linear addressing!");
236 return 0;
237 }
238 memset(ScreenLoc,0,320*240);
239 break;
240 }
241 vidready|=2;
242 FlushPalette(); // Needed for cheat console code(and it isn't a bad thing to do anyway...).
243 return 1;
244}
245
246void KillVideo(void)
247{
248 if(vidready)
249 {
250 vga_setmode(TEXT);
251 vidready=0;
252 }
253}
254
255
256void BlitScreen(uint8 *XBuf)
257{
258 static int conto=0;
259 uint8 *dest;
260 int tlines;
261 #ifdef DUMMY
262 return;
263 #endif
264 #ifdef FRAMESKIP
265 FCEUI_FrameSkip(FCEUDfskip);
266 #endif
267
268 if(doptions&DO_VSYNC && !NoWaiting)
269 {
270 vga_waitretrace();
271 }
272
273 tlines=erendline-srendline+1;
274
275 dest=ScreenLoc;
276
277 if(vmode!=4 && vmode!=5 && vmode!=7)
278 {
279 conto=(conto+1)&0x3F;
280 if(!conto) vcfix();
281 }
282 switch(vmode)
283 {
284 case 1:dest+=(((240-tlines)>>1)<<8);break;
285 case 2:
286 case 3:dest+=(((256-tlines)>>1)<<8);break;
287 case 4:
288 case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break;
289 case 8:
290 case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break;
291 case 7:dest+=(((240-tlines)>>1)*320)+32;break;
292 }
293
294 XBuf+=(srendline<<8)+(srendline<<4);
295
296 if(eoptions&EO_CLIPSIDES)
297 {
298 if(vmode==5)
299 {
300 asm volatile(
301 "xorl %%edx, %%edx\n\t"
302 "ckoop1:\n\t"
303 "movb $120,%%al \n\t"
304 "ckoop2:\n\t"
305 "movb 1(%%esi),%%dl\n\t"
306 "shl $16,%%edx\n\t"
307 "movb (%%esi),%%dl\n\t"
308 "xorl $0x00800080,%%edx\n\t"
309 "movl %%edx,(%%edi)\n\t"
310 "addl $2,%%esi\n\t"
311 "addl $4,%%edi\n\t"
312 "decb %%al\n\t"
313 "jne ckoop2\n\t"
314
315 "addl $32,%%esi\n\t"
316 "addl $800,%%edi\n\t"
317 "decb %%bl\n\t"
318 "jne ckoop1\n\t"
319 :
320 : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
321 : "%al", "%edx", "%cc" );
322 }
323 else if(vmode==4)
324 {
325 asm volatile(
326 "cyoop1:\n\t"
327 "movb $120,%%al \n\t"
328 "cyoop2:\n\t"
329 "movb 1(%%esi),%%dh\n\t"
330 "movb %%dh,%%dl\n\t"
331 "shl $16,%%edx\n\t"
332 "movb (%%esi),%%dl\n\t"
333 "movb %%dl,%%dh\n\t" // Ugh
334 "xorl $0x80808080,%%edx\n\t"
335 "movl %%edx,(%%edi)\n\t"
336 "addl $2,%%esi\n\t"
337 "addl $4,%%edi\n\t"
338 "decb %%al\n\t"
339 "jne cyoop2\n\t"
340
341 "addl $32,%%esi\n\t"
342 "addl $800,%%edi\n\t"
343 "decb %%bl\n\t"
344 "jne cyoop1\n\t"
345 :
346 : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
347 : "%al", "%edx", "%cc" );
348 }
349 else if(vmode==7)
350 {
351 asm volatile(
352 "cgoop81:\n\t"
353 "movl $30,%%eax\n\t"
354 "cgoop82:\n\t"
355 "movl (%%esi),%%edx\n\t"
356 "movl 4(%%esi),%%ecx\n\t"
357 "xorl $0x80808080,%%edx\n\t"
358 "xorl $0x80808080,%%ecx\n\t"
359 "movl %%edx,(%%edi)\n\t"
360 "movl %%ecx,4(%%edi)\n\t"
361 "addl $8,%%esi\n\t"
362 "addl $8,%%edi\n\t"
363 "decl %%eax\n\t"
364 "jne cgoop82\n\t"
365 "addl $80,%%edi\n\t"
366 "addl $32,%%esi\n\t"
367 "decb %%bl\n\t"
368 "jne cgoop81\n\t"
369 :
370 : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
371 : "%eax","%cc","%edx","%ecx" );
372 }
373 else
374 {
375 asm volatile(
376 "cgoop1:\n\t"
377 "movl $30,%%eax\n\t"
378 "cgoop2:\n\t"
379 "movl (%%esi),%%edx\n\t"
380 "movl 4(%%esi),%%ecx\n\t"
381 "movl %%edx,(%%edi)\n\t"
382 "movl %%ecx,4(%%edi)\n\t"
383 "addl $8,%%esi\n\t"
384 "addl $8,%%edi\n\t"
385 "decl %%eax\n\t"
386 "jne cgoop2\n\t"
387 "addl $32,%%esi\n\t"
388 "addl $16,%%edi\n\t"
389 "decb %%bl\n\t"
390 "jne cgoop1\n\t"
391 :
392 : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
393 : "%eax","%cc","%edx","%ecx" );
394 }
395 }
396 else
397 {
398 if(vmode==5)
399 {
400 asm volatile(
401 "xorl %%edx, %%edx\n\t"
402 "koop1:\n\t"
403 "movb $128,%%al \n\t"
404 "koop2:\n\t"
405 "movb 1(%%esi),%%dl\n\t"
406 "shl $16,%%edx\n\t"
407 "movb (%%esi),%%dl\n\t"
408 "xorl $0x00800080,%%edx\n\t"
409 "movl %%edx,(%%edi)\n\t"
410 "addl $2,%%esi\n\t"
411 "addl $4,%%edi\n\t"
412 "decb %%al\n\t"
413 "jne koop2\n\t"
414
415 "addl $16,%%esi\n\t"
416 "addl $768,%%edi\n\t"
417 "decb %%bl\n\t"
418 "jne koop1\n\t"
419 :
420 : "S" (XBuf), "D" (dest), "b" (tlines)
421 : "%al", "%edx", "%cc" );
422 }
423 else if(vmode==4)
424 {
425 asm volatile(
426 "yoop1:\n\t"
427 "movb $128,%%al \n\t"
428 "yoop2:\n\t"
429 "movb 1(%%esi),%%dh\n\t"
430 "movb %%dh,%%dl\n\t"
431 "shl $16,%%edx\n\t"
432 "movb (%%esi),%%dl\n\t"
433 "movb %%dl,%%dh\n\t" // Ugh
434 "xorl $0x80808080,%%edx\n\t"
435 "movl %%edx,(%%edi)\n\t"
436 "addl $2,%%esi\n\t"
437 "addl $4,%%edi\n\t"
438 "decb %%al\n\t"
439 "jne yoop2\n\t"
440
441 "addl $16,%%esi\n\t"
442 "addl $768,%%edi\n\t"
443 "decb %%bl\n\t"
444 "jne yoop1\n\t"
445 :
446 : "S" (XBuf), "D" (dest), "b" (tlines)
447 : "%al", "%edx", "%cc" );
448 }
449 else if(vmode==7)
450 {
451 asm volatile(
452 "goop81:\n\t"
453 "movl $32,%%eax\n\t"
454 "goop82:\n\t"
455 "movl (%%esi),%%edx\n\t"
456 "movl 4(%%esi),%%ecx\n\t"
457 "xorl $0x80808080,%%edx\n\t"
458 "xorl $0x80808080,%%ecx\n\t"
459 "movl %%edx,(%%edi)\n\t"
460 "movl %%ecx,4(%%edi)\n\t"
461 "addl $8,%%esi\n\t"
462 "addl $8,%%edi\n\t"
463 "decl %%eax\n\t"
464 "jne goop82\n\t"
465 "addl $64,%%edi\n\t"
466 "addl $16,%%esi\n\t"
467 "decb %%bl\n\t"
468 "jne goop81\n\t"
469 :
470 : "S" (XBuf), "D" (dest), "b" (tlines)
471 : "%eax","%cc","%edx","%ecx" );
472 }
473 else
474 {
475 asm volatile(
476 "goop1:\n\t"
477 "movl $32,%%eax\n\t"
478 "goop2:\n\t"
479 "movl (%%esi),%%edx\n\t"
480 "movl 4(%%esi),%%ecx\n\t"
481 "movl %%edx,(%%edi)\n\t"
482 "movl %%ecx,4(%%edi)\n\t"
483 "addl $8,%%esi\n\t"
484 "addl $8,%%edi\n\t"
485 "decl %%eax\n\t"
486 "jne goop2\n\t"
487 "addl $16,%%esi\n\t"
488 "decb %%bl\n\t"
489 "jne goop1\n\t"
490 :
491 : "S" (XBuf), "D" (dest), "b" (tlines)
492 : "%eax","%cc","%edx","%ecx" );
493 }
494 }
495}
496
497