1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 static int RecalcCustom(void);
23 #define VF_DDSTRETCHED 1
25 #define VEF_LOSTSURFACE 1
26 #define VEF____INTERNAL 2
42 // left, top, right, bottom
43 static vmdef vmodes[11]={
44 {320,240,8,0,1,1}, //0
45 {320,240,8,0,1,1}, //1
46 {512,384,8,0,1,1}, //2
47 {640,480,8,0,1,1}, //3
48 {640,480,8,0,1,1}, //4
49 {640,480,8,0,1,1}, //5
50 {640,480,8,VMDF_DXBLT,2,2}, //6
51 {1024,768,8,VMDF_DXBLT,4,3}, //7
52 {1280,1024,8,VMDF_DXBLT,5,4}, //8
53 {1600,1200,8,VMDF_DXBLT,6,5}, //9
54 {800,600,8,VMDF_DXBLT|VMDF_STRFS,0,0} //10
57 static int mustrestore=0;
67 static uint32 *palettetranslate=0;
69 PALETTEENTRY color_palette[256];
70 static int PaletteChanged=0;
72 LPDIRECTDRAWCLIPPER lpClipper=0;
74 LPDIRECTDRAW4 lpDD4=0;
75 LPDIRECTDRAWPALETTE lpddpal;
79 DDSURFACEDESC2 ddsdback;
80 LPDIRECTDRAWSURFACE4 lpDDSPrimary=0;
81 LPDIRECTDRAWSURFACE4 lpDDSDBack=0;
82 LPDIRECTDRAWSURFACE4 lpDDSBack=0;
84 static void ShowDDErr(char *s)
87 sprintf(tempo,"DirectDraw: %s",s);
88 FCEUD_PrintError(tempo);
95 if(!lpDDSBack) return 0;
96 if(IDirectDrawSurface4_Restore(lpDDSBack)!=DD_OK) return 0;
100 if(!lpDDSPrimary) return 0;
101 if(IDirectDrawSurface4_Restore(lpDDSPrimary)!=DD_OK) return 0;
107 void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
109 color_palette[index].peRed=r;
110 color_palette[index].peGreen=g;
111 color_palette[index].peBlue=b;
115 void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b)
117 *r=color_palette[i].peRed;
118 *g=color_palette[i].peGreen;
119 *b=color_palette[i].peBlue;
122 int InitializeDDraw(void)
124 ddrval = DirectDrawCreate(NULL, &lpDD, NULL);
127 ShowDDErr("Error creating DirectDraw object.");
131 ddrval = IDirectDraw_QueryInterface(lpDD,&IID_IDirectDraw4,(LPVOID *)&lpDD4);
132 IDirectDraw_Release(lpDD);
136 ShowDDErr("Error querying interface.");
140 caps.dwSize=sizeof(caps);
141 if(IDirectDraw4_GetCaps(lpDD4,&caps,0)!=DD_OK)
143 ShowDDErr("Error getting capabilities.");
149 static int GetBPP(void)
153 memset(&ddpix,0,sizeof(ddpix));
154 ddpix.dwSize=sizeof(ddpix);
156 ddrval=IDirectDrawSurface4_GetPixelFormat(lpDDSPrimary,&ddpix);
159 ShowDDErr("Error getting primary surface pixel format.");
163 if(ddpix.dwFlags&DDPF_RGB)
165 bpp=ddpix.DUMMYUNIONNAMEN(1).dwRGBBitCount;
166 CBM[0]=ddpix.DUMMYUNIONNAMEN(2).dwRBitMask;
167 CBM[1]=ddpix.DUMMYUNIONNAMEN(3).dwGBitMask;
168 CBM[2]=ddpix.DUMMYUNIONNAMEN(4).dwBBitMask;
172 ShowDDErr("RGB data not valid.");
180 static int InitBPPStuff(void)
183 palettetranslate=malloc(65536*4);
185 palettetranslate=malloc(256*4);
188 ddrval=IDirectDraw4_CreatePalette( lpDD4, DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,color_palette,&lpddpal,NULL);
191 ShowDDErr("Error creating palette object.");
194 ddrval=IDirectDrawSurface4_SetPalette(lpDDSPrimary, lpddpal);
197 ShowDDErr("Error setting palette object.");
204 int SetVideoMode(int fs)
206 if(!lpDD4) // DirectDraw not initialized
226 ddrval = IDirectDraw4_SetCooperativeLevel ( lpDD4, hAppWnd, DDSCL_NORMAL);
229 ShowDDErr("Error setting cooperative level.");
234 memset(&ddsd,0,sizeof(ddsd));
235 ddsd.dwSize = sizeof(ddsd);
236 ddsd.dwFlags = DDSD_CAPS;
237 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
239 ddrval = IDirectDraw4_CreateSurface ( lpDD4, &ddsd, &lpDDSPrimary,(IUnknown FAR*)NULL);
242 ShowDDErr("Error creating primary surface.");
246 memset(&ddsdback,0,sizeof(ddsdback));
247 ddsdback.dwSize=sizeof(ddsdback);
248 ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
249 ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
251 ddsdback.dwWidth=256;
252 ddsdback.dwHeight=240;
254 /* If no blit hardware is present, make sure buffer is created
257 if(!(caps.dwCaps&DDCAPS_BLT))
258 ddsdback.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
260 ddrval = IDirectDraw4_CreateSurface ( lpDD4, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL);
263 ShowDDErr("Error creating secondary surface.");
270 if(bpp!=16 && bpp!=24 && bpp!=32)
272 ShowDDErr("Current bit depth not supported!");
279 ddrval=IDirectDraw4_CreateClipper(lpDD4,0,&lpClipper,0);
282 ShowDDErr("Error creating clipper.");
286 ddrval=IDirectDrawClipper_SetHWnd(lpClipper,0,hAppWnd);
289 ShowDDErr("Error setting clipper window.");
292 ddrval=IDirectDrawSurface4_SetClipper(lpDDSPrimary,lpClipper);
295 ShowDDErr("Error attaching clipper to primary surface.");
300 SetMainWindowStuff();
306 ddrval = IDirectDraw4_SetCooperativeLevel ( lpDD4, hAppWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
309 ShowDDErr("Error setting cooperative level.");
313 ddrval = IDirectDraw4_SetDisplayMode(lpDD4, vmodes[vmod].x, vmodes[vmod].y,vmodes[vmod].bpp,0,0);
316 ShowDDErr("Error setting display mode.");
319 if(vmodes[vmod].flags&VMDF_DXBLT)
321 memset(&ddsdback,0,sizeof(ddsdback));
322 ddsdback.dwSize=sizeof(ddsdback);
323 ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
324 ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
326 ddsdback.dwWidth=256; //vmodes[vmod].srect.right;
327 ddsdback.dwHeight=240; //vmodes[vmod].srect.bottom;
329 if(!(caps.dwCaps&DDCAPS_BLT))
330 ddsdback.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
332 ddrval = IDirectDraw4_CreateSurface ( lpDD4, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL);
335 ShowDDErr("Error creating secondary surface.");
340 // create foreground surface
342 memset(&ddsd,0,sizeof(ddsd));
343 ddsd.dwSize = sizeof(ddsd);
345 ddsd.dwFlags = DDSD_CAPS;
346 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
348 if(fssync==2) // Double buffering.
350 ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
351 ddsd.dwBackBufferCount = 1;
352 ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
355 ddrval = IDirectDraw4_CreateSurface ( lpDD4, &ddsd, &lpDDSPrimary,(IUnknown FAR*)NULL);
358 ShowDDErr("Error creating primary surface.");
366 memset(&tmp,0,sizeof(tmp));
367 tmp.dwCaps=DDSCAPS_BACKBUFFER;
369 if(IDirectDrawSurface4_GetAttachedSurface(lpDDSPrimary,&tmp,&lpDDSDBack)!=DD_OK)
371 ShowDDErr("Error getting attached surface.");
385 InputScreenChanged(fs);
390 static void BlitScreenWindow(uint8 *XBuf);
391 static void BlitScreenFull(uint8 *XBuf);
393 void FCEUD_BlitScreen(uint8 *XBuf)
399 if(!(eoptions&EO_BGRUN))
407 /* This complex statement deserves some explanation.
408 Make sure this special speed throttling hasn't been disabled by the user
409 first. Second, we don't want to throttle the speed if the fast-forward
410 button is pressed down(or during certain network play conditions).
412 Now, if we're at this point, we'll throttle speed if sound is disabled.
413 Otherwise, it gets a bit more complicated. We'll throttle speed if focus
414 to FCE Ultra has been lost and we're writing to the primary sound buffer
415 because our sound code won't block. Blocking does seem to work when
416 writing to a secondary buffer, so we won't throttle when a secondary
420 if(!(eoptions&EO_NOTHROTTLE))
422 if(!soundo || (soundo && nofocus && !(soundoptions&SO_SECONDARY)) )
427 if(fssync==1 && !NoWaiting)
428 IDirectDraw4_WaitForVerticalBlank(lpDD4,DDWAITVB_BLOCKBEGIN,0);
430 BlitScreenFull(XBuf);
434 if(winsync && !NoWaiting)
435 IDirectDraw4_WaitForVerticalBlank(lpDD4,DDWAITVB_BLOCKBEGIN,0);
438 BlitScreenWindow(XBuf);
449 static INLINE void BlitVidHi(uint8 *src, uint8 *dest, /*int xr,*/ int yr, int pitch)
454 if(!(eoptions&EO_CLIPSIDES))
464 *(uint32 *)dest=palettetranslate[(uint32)*src];
480 tmp=palettetranslate[(uint32)*src];
481 *(uint16*)dest=(uint16)tmp;
482 *&dest[2]=(uint8)(tmp>>16);
497 *(unsigned long *)dest=palettetranslate[*(unsigned short *)src];
516 *(uint32 *)dest=palettetranslate[(uint32)*src];
532 tmp=palettetranslate[(uint32)*src];
533 *(uint16*)dest=(uint16)tmp;
534 *&dest[2]=(uint8)(tmp>>16);
548 *(unsigned long *)dest=palettetranslate[*(unsigned short *)src];
559 static INLINE void FixPaletteHi(void)
570 cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
573 for(x=0,y=-1,z=0;x<16;x++)
577 if(cshiftl[a]==-1) cshiftl[a]=x;
587 lower=(color_palette[x&255].peRed>>cshiftr[0])<<cshiftl[0];
588 lower|=(color_palette[x&255].peGreen>>cshiftr[1])<<cshiftl[1];
589 lower|=(color_palette[x&255].peBlue>>cshiftr[2])<<cshiftl[2];
590 upper=(color_palette[x>>8].peRed>>cshiftr[0])<<cshiftl[0];
591 upper|=(color_palette[x>>8].peGreen>>cshiftr[1])<<cshiftl[1];
592 upper|=(color_palette[x>>8].peBlue>>cshiftr[2])<<cshiftl[2];
593 palettetranslate[x]=lower|(upper<<16);
603 t=color_palette[x].peBlue;
604 t|=color_palette[x].peGreen<<8;
605 t|=color_palette[x].peRed<<16;
606 palettetranslate[x]=t;
612 static void BlitScreenWindow(unsigned char *XBuf)
615 unsigned char *ScreenLoc;
619 srect.top=srect.left=0;
621 srect.bottom=totallines;
623 if(PaletteChanged==1)
628 if(!GetClientAbsRect(&drect)) return;
630 ddrval=IDirectDrawSurface4_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL);
633 if(ddrval==DDERR_SURFACELOST) RestoreDD(1);
636 pitch=ddsdback.DUMMYUNIONNAMEN(1).lPitch;
637 ScreenLoc=ddsdback.lpSurface;
641 memset(ScreenLoc,0,pitch*240);
645 BlitVidHi(XBuf+srendline*272+VNSCLIP, ScreenLoc, /*VNSWID,*/ totallines, pitch);
647 IDirectDrawSurface4_Unlock(lpDDSBack, NULL);
649 if(IDirectDrawSurface4_Blt(lpDDSPrimary, &drect,lpDDSBack,&srect,DDBLT_ASYNC,0)!=DD_OK)
651 ddrval=IDirectDrawSurface4_Blt(lpDDSPrimary, &drect,lpDDSBack,&srect,DDBLT_WAIT,0);
654 if(ddrval==DDERR_SURFACELOST) {RestoreDD(1);RestoreDD(0);}
660 static void BlitScreenFull(uint8 *XBuf)
667 LPDIRECTDRAWSURFACE4 lpDDSVPrimary;
671 lpDDSVPrimary=lpDDSDBack;
673 lpDDSVPrimary=lpDDSPrimary;
675 if(PaletteChanged==1)
680 for(x=0;x<=0x80;x+=0x80)
682 ddrval=IDirectDrawPalette_SetEntries(lpddpal,0,0x80^x,128,&color_palette[x]);
685 if(ddrval==DDERR_SURFACELOST) RestoreDD(0);
692 if(vmodes[vmod].flags&VMDF_DXBLT)
694 ddrval=IDirectDrawSurface4_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL);
697 if(ddrval==DDERR_SURFACELOST) RestoreDD(1);
700 ScreenLoc=ddsdback.lpSurface;
701 pitch=ddsdback.DUMMYUNIONNAMEN(1).lPitch;
706 srect.bottom=totallines;
707 if(vmodes[vmod].flags&VMDF_STRFS)
711 drect.right=vmodes[vmod].x;
712 drect.bottom=vmodes[vmod].y;
716 drect.top=(vmodes[vmod].y-(totallines*vmodes[vmod].yscale))>>1;
717 drect.bottom=drect.top+(totallines*vmodes[vmod].yscale);
718 drect.left=(vmodes[vmod].x-VNSWID*vmodes[vmod].xscale)>>1;
719 drect.right=drect.left+VNSWID*vmodes[vmod].xscale;
724 ddrval=IDirectDrawSurface4_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL);
727 if(ddrval==DDERR_SURFACELOST) RestoreDD(0);
731 ScreenLoc=ddsd.lpSurface;
732 pitch=ddsd.DUMMYUNIONNAMEN(1).lPitch;
737 if(vmodes[vmod].flags&VMDF_DXBLT)
740 memset((char *)ScreenLoc,0,pitch*srect.bottom);
744 memset((char *)ScreenLoc,0,pitch*vmodes[vmod].y);
752 if(eoptions&EO_CLIPSIDES)
755 "xorl %%edx, %%edx\n\t"
757 "movb $120,%%al \n\t"
759 "movb 1(%%esi),%%dl\n\t"
761 "movb (%%esi),%%dl\n\t"
762 "xorl $0x00800080,%%edx\n\t"
763 "movl %%edx,(%%edi)\n\t"
769 "addl %%ecx,%%edi\n\t"
773 : "S" (XBuf+srendline*272+VNSCLIP), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-(VNSWID<<1))/2),"b" (totallines), "c" ((pitch-VNSWID)<<1)
774 : "%al", "%edx", "%cc" );
779 "xorl %%edx, %%edx\n\t"
781 "movb $128,%%al \n\t"
783 "movb 1(%%esi),%%dl\n\t"
785 "movb (%%esi),%%dl\n\t"
786 "xorl $0x00800080,%%edx\n\t"
787 "movl %%edx,(%%edi)\n\t"
793 "addl %%ecx,%%edi\n\t"
797 : "S" (XBuf+srendline*272), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-512)/2),"b" (totallines), "c" (pitch-512+pitch)
798 : "%al", "%edx", "%cc" );
803 if(eoptions&EO_CLIPSIDES)
807 "movb $120,%%al \n\t"
809 "movb 1(%%esi),%%dh\n\t"
812 "movb (%%esi),%%dl\n\t"
813 "movb %%dl,%%dh\n\t" // Ugh
814 "xorl $0x80808080,%%edx\n\t"
815 "movl %%edx,(%%edi)\n\t"
821 "addl %%ecx,%%edi\n\t"
825 : "S" (XBuf+srendline*272+VNSCLIP), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-(VNSWID<<1))/2),"b" (totallines), "c" ((pitch-VNSWID)<<1)
826 : "%al", "%edx", "%cc" );
832 "movb $128,%%al \n\t"
834 "movb 1(%%esi),%%dh\n\t"
837 "movb (%%esi),%%dl\n\t"
838 "movb %%dl,%%dh\n\t" // Ugh
839 "xorl $0x80808080,%%edx\n\t"
840 "movl %%edx,(%%edi)\n\t"
846 "addl %%ecx,%%edi\n\t"
850 : "S" (XBuf+srendline*272), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-512)/2),"b" (totallines), "c" (pitch-512+pitch)
851 : "%al", "%edx", "%cc" );
856 if(!(vmodes[vmod].flags&VMDF_DXBLT))
858 ScreenLoc+=((vmodes[vmod].x-VNSWID)>>1)*(bpp>>3)+(((vmodes[vmod].y-totallines)>>1))*pitch;
862 BlitVidHi(XBuf+srendline*272+VNSCLIP, ScreenLoc, /*VNSWID,*/ totallines, pitch);
866 XBuf+=srendline*272+VNSCLIP;
867 if(eoptions&EO_CLIPSIDES)
869 for(y=totallines;y;y--)
873 *(long *)ScreenLoc=(*(long *)XBuf)^0x80808080;
877 ScreenLoc+=pitch-240;
883 for(y=totallines;y;y--)
887 *(long *)ScreenLoc=(*(long *)XBuf)^0x80808080;
891 ScreenLoc+=pitch-256;
898 if(vmodes[vmod].flags&VMDF_DXBLT)
900 IDirectDrawSurface4_Unlock(lpDDSBack, NULL);
904 if(IDirectDrawSurface4_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL)==DD_OK)
906 memset(ddsd.lpSurface,0,ddsd.DUMMYUNIONNAMEN(1).lPitch*vmodes[vmod].y);
907 IDirectDrawSurface4_Unlock(lpDDSVPrimary, NULL);
913 if(IDirectDrawSurface4_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_ASYNC,0)!=DD_OK)
915 ddrval=IDirectDrawSurface4_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_WAIT,0);
918 if(ddrval==DDERR_SURFACELOST)
929 IDirectDrawSurface4_Unlock(lpDDSVPrimary, NULL);
932 IDirectDrawSurface4_Flip(lpDDSPrimary,0,0);
937 void ResetVideo(void)
940 if(palettetranslate) {free(palettetranslate);palettetranslate=0;}
943 {IDirectDraw4_RestoreDisplayMode(lpDD4);mustrestore=0;}
944 if(lpDDSBack) {IDirectDrawSurface4_Release(lpDDSBack);lpDDSBack=0;}
945 if(lpDDSPrimary) {IDirectDrawSurface4_Release(lpDDSPrimary);lpDDSPrimary=0;}
946 if(lpClipper) {IDirectDrawClipper_Release(lpClipper);lpClipper=0;}
949 static int RecalcCustom(void)
951 vmodes[0].flags&=~VMDF_DXBLT;
953 if(vmodes[0].flags&VMDF_STRFS)
955 vmodes[0].flags|=VMDF_DXBLT;
957 vmodes[0].srect.top=srendline;
958 vmodes[0].srect.left=VNSCLIP;
959 vmodes[0].srect.right=256-VNSCLIP;
960 vmodes[0].srect.bottom=erendline+1;
962 vmodes[0].drect.top=vmodes[0].drect.left=0;
963 vmodes[0].drect.right=vmodes[0].x;
964 vmodes[0].drect.bottom=vmodes[0].y;
966 else if(vmodes[0].xscale!=1 || vmodes[0].yscale!=1)
968 vmodes[0].flags|=VMDF_DXBLT;
969 if(VNSWID*vmodes[0].xscale>vmodes[0].x)
971 FCEUD_PrintError("Scaled width is out of range. Reverting to no horizontal scaling.");
974 if(totallines*vmodes[0].yscale>vmodes[0].y)
976 FCEUD_PrintError("Scaled height is out of range. Reverting to no vertical scaling.");
980 vmodes[0].srect.left=VNSCLIP;
981 vmodes[0].srect.top=srendline;
982 vmodes[0].srect.right=256-VNSCLIP;
983 vmodes[0].srect.bottom=erendline+1;
985 vmodes[0].drect.top=(vmodes[0].y-(totallines*vmodes[0].yscale))>>1;
986 vmodes[0].drect.bottom=vmodes[0].drect.top+totallines*vmodes[0].yscale;
988 vmodes[0].drect.left=(vmodes[0].x-(VNSWID*vmodes[0].xscale))>>1;
989 vmodes[0].drect.right=vmodes[0].drect.left+VNSWID*vmodes[0].xscale;
992 if(vmodes[0].x<VNSWID)
994 FCEUD_PrintError("Horizontal resolution is too low.");
997 if(vmodes[0].y<totallines && !(vmodes[0].flags&VMDF_STRFS))
999 FCEUD_PrintError("Vertical resolution must not be less than the total number of drawn scanlines.");
1006 BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1008 static char *vmstr[11]={
1010 "320x240 Full Screen",
1013 "640x480 Scanlines",
1014 "640x480 \"4 per 1\"",
1027 SendDlgItemMessage(hwndDlg,100,CB_ADDSTRING,0,(LPARAM)(LPSTR)vmstr[x]);
1028 SendDlgItemMessage(hwndDlg,100,CB_SETCURSEL,vmod,(LPARAM)(LPSTR)0);
1030 SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"8");
1031 SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"16");
1032 SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"24");
1033 SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"32");
1034 SendDlgItemMessage(hwndDlg,202,CB_SETCURSEL,(vmodes[0].bpp>>3)-1,(LPARAM)(LPSTR)0);
1036 SetDlgItemInt(hwndDlg,200,vmodes[0].x,0);
1037 SetDlgItemInt(hwndDlg,201,vmodes[0].y,0);
1039 SetDlgItemInt(hwndDlg,302,vmodes[0].xscale,0);
1040 SetDlgItemInt(hwndDlg,303,vmodes[0].yscale,0);
1041 CheckRadioButton(hwndDlg,300,301,(vmodes[0].flags&VMDF_STRFS)?301:300);
1042 if(eoptions&EO_FSAFTERLOAD)
1043 CheckDlgButton(hwndDlg,102,BST_CHECKED);
1045 if(eoptions&EO_CLIPSIDES)
1046 CheckDlgButton(hwndDlg,106,BST_CHECKED);
1048 SetDlgItemInt(hwndDlg,500,srendlinen,0);
1049 SetDlgItemInt(hwndDlg,501,erendlinen,0);
1051 SetDlgItemInt(hwndDlg,502,srendlinep,0);
1052 SetDlgItemInt(hwndDlg,503,erendlinep,0);
1055 SetDlgItemInt(hwndDlg,103,winsizemul,0);
1057 SendDlgItemMessage(hwndDlg,104,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
1058 SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
1060 SendDlgItemMessage(hwndDlg,104,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Wait for VBlank");
1061 SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Wait for VBlank");
1063 SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Double Buffering");
1065 SendDlgItemMessage(hwndDlg,104,CB_SETCURSEL,winsync,(LPARAM)(LPSTR)0);
1066 SendDlgItemMessage(hwndDlg,105,CB_SETCURSEL,fssync,(LPARAM)(LPSTR)0);
1069 case WM_QUIT: goto gornk;
1072 switch(wParam&0xFFFF)
1077 if(IsDlgButtonChecked(hwndDlg,106)==BST_CHECKED)
1078 eoptions|=EO_CLIPSIDES;
1080 eoptions&=~EO_CLIPSIDES;
1082 srendlinen=GetDlgItemInt(hwndDlg,500,0,0);
1083 erendlinen=GetDlgItemInt(hwndDlg,501,0,0);
1084 srendlinep=GetDlgItemInt(hwndDlg,502,0,0);
1085 erendlinep=GetDlgItemInt(hwndDlg,503,0,0);
1088 if(erendlinen>239) erendlinen=239;
1089 if(srendlinen>erendlinen) srendlinen=erendlinen;
1091 if(erendlinep>239) erendlinep=239;
1092 if(srendlinep>erendlinen) srendlinep=erendlinep;
1096 if(IsDlgButtonChecked(hwndDlg,301)==BST_CHECKED)
1097 vmodes[0].flags|=VMDF_STRFS;
1099 vmodes[0].flags&=~VMDF_STRFS;
1101 vmod=SendDlgItemMessage(hwndDlg,100,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
1102 vmodes[0].x=GetDlgItemInt(hwndDlg,200,0,0);
1103 vmodes[0].y=GetDlgItemInt(hwndDlg,201,0,0);
1104 vmodes[0].bpp=(SendDlgItemMessage(hwndDlg,202,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)+1)<<3;
1106 vmodes[0].xscale=GetDlgItemInt(hwndDlg,302,0,0);
1107 vmodes[0].yscale=GetDlgItemInt(hwndDlg,303,0,0);
1109 if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)
1113 if(IsDlgButtonChecked(hwndDlg,102)==BST_CHECKED)
1114 eoptions|=EO_FSAFTERLOAD;
1116 eoptions&=~EO_FSAFTERLOAD;
1119 int t=GetDlgItemInt(hwndDlg,103,0,0);
1123 winsync=SendDlgItemMessage(hwndDlg,104,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
1124 fssync=SendDlgItemMessage(hwndDlg,105,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
1125 EndDialog(hwndDlg,0);
1132 static void SetFSVideoMode(void)
1135 if(!SetVideoMode(1))
1142 void ConfigVideo(void)
1144 DialogBox(fceu_hInstance,"VIDEOCONFIG",hAppWnd,VideoConCallB);
1149 SetMainWindowStuff();
1152 void DoVideoConfigFix(void)
1161 if(vmodes[0].x<VNSWID)
1163 FCEUD_PrintError("Horizontal resolution is too low.");
1166 if(vmodes[0].y<totallines && !(vmodes[0].flags&VMDF_STRFS))
1168 FCEUD_PrintError("Vertical resolution must not be less than the total number of drawn scanlines.");