gpfce patch part2
[fceu.git] / drivers / cli / svga-video.c
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
36 int vmode=1;
37
38 #ifdef FRAMESKIP
39 int FCEUDfskip=0;
40 #endif
41
42 static int vidready=0;
43 static int conlock=0;
44
45 void LockConsole(void)
46 {
47  if(!conlock)
48  {
49   vga_lockvc();
50   conlock=1;
51   FCEUI_DispMessage("Console locked.");
52  }
53 }
54
55 void UnlockConsole(void)
56 {
57  if(conlock)
58  {
59   vga_unlockvc();
60   conlock=0;
61   FCEUI_DispMessage("Console unlocked.");
62  }
63 }
64
65 void 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
78 void 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
109 static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
110
111 static 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
122 void 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
136 void 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
143 static 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
160 static uint8 *ScreenLoc;
161
162 int 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
246 void KillVideo(void)
247 {
248  if(vidready)
249  {
250   vga_setmode(TEXT);
251   vidready=0;
252  }
253 }
254
255
256 void 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