1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
5 * Copyright (C) 2002 Ben Parnell
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.
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.
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
22 /* SVGA High Level Routines
34 #define M_PI 3.14159265358979323846
57 static char errmsg[65];
59 void FCEU_PrintError(char *format, ...)
66 vsprintf(temp,format,ap);
67 FCEUD_PrintError(temp);
72 void FCEU_DispMessage(char *format, ...)
77 vsprintf(errmsg,format,ap);
82 printf("%s\n", errmsg);
85 void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall)
87 FSettings.UsrFirstSLine[0]=ntscf;
88 FSettings.UsrLastSLine[0]=ntscl;
89 FSettings.UsrFirstSLine[1]=palf;
90 FSettings.UsrLastSLine[1]=pall;
93 FSettings.FirstSLine=FSettings.UsrFirstSLine[1];
94 FSettings.LastSLine=FSettings.UsrLastSLine[1];
98 FSettings.FirstSLine=FSettings.UsrFirstSLine[0];
99 FSettings.LastSLine=FSettings.UsrLastSLine[0];
104 void FCEUI_SetVidSystem(int a)
111 int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
114 *slstart=FSettings.FirstSLine;
116 *slend=FSettings.LastSLine;
121 void FCEUI_SetNetworkPlay(int type)
123 FSettings.NetworkPlay=type;
127 void FCEUI_SetGameGenie(int a)
129 FSettings.GameGenie=a?1:0;
136 static uint8 StateShow=0;
145 uint8 CommandQueue=0;
147 static int controlselect=0;
148 static int ntsccol=0;
149 static int ntsctint=46+10;
150 static int ntschue=72;
151 static int controllength=0;
155 static pal *palpoint[8]=
168 void FCEUI_SetSnapName(int a)
170 FSettings.SnapName=a;
173 void FCEUI_SaveExtraDataUnderBase(int a)
175 FSettings.SUnderBase=a;
179 void FCEUI_SetPaletteArray(uint8 *pal)
186 palpoint[0]=palettec;
189 palpoint[0][x].r=*((uint8 *)pal+x+x+x);
190 palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);
191 palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);
198 void FCEUI_SelectState(int w)
200 if(netplay!=2 && FCEUGameInfo.type!=GIT_NSF)
204 void FCEUI_SaveState(void)
206 if(netplay!=2 && FCEUGameInfo.type!=GIT_NSF)
210 void FCEUI_LoadState(void)
212 if(netplay!=2 && FCEUGameInfo.type!=GIT_NSF)
216 int32 FCEUI_GetDesiredFPS(void)
219 return(838977920); // ~50.007
221 return(1008307711); // ~60.1
224 static int dosnapsave=0;
225 void FCEUI_SaveSnapshot(void)
230 /* I like the sounds of breaking necks. */
231 static void ReallySnap(void)
233 int x=SaveSnapshot();
235 FCEU_DispMessage("Error saving screen snapshot.");
237 FCEU_DispMessage("Screen snapshot %d saved.",x-1);
240 void DriverInterface(int w, void *d)
244 case DES_NTSCCOL:ntsccol=*(int *)d;FCEU_ResetPalette();break;
245 case DES_RESET:if(netplay!=2) CommandQueue=30;break;
246 case DES_POWER:if(netplay!=2) CommandQueue=31;break;
247 case DES_GETNTSCTINT:*(int*)d=ntsctint;break;
248 case DES_GETNTSCHUE:*(int*)d=ntschue;break;
249 case DES_SETNTSCTINT:ntsctint=*(int*)d;if(ntsccol)FCEU_ResetPalette();break;
250 case DES_SETNTSCHUE:ntschue=*(int*)d;if(ntsccol)FCEU_ResetPalette();break;
252 case DES_FDSINSERT:if(netplay!=2) CommandQueue=2;break;
253 case DES_FDSEJECT:if(netplay!=2) CommandQueue=3;break;
254 case DES_FDSSELECT:if(netplay!=2) CommandQueue=1;break;
256 case DES_NSFINC:NSFControl(1);break;
257 case DES_NSFDEC:NSFControl(2);break;
258 case DES_NSFRES:NSFControl(0);break;
260 case DES_VSUNIDIPSET:CommandQueue=10+(int)d;break;
261 case DES_VSUNITOGGLEDIPVIEW:CommandQueue=10;break;
262 case DES_VSUNICOIN:CommandQueue=19;break;
263 case DES_NTSCSELHUE:if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=1;controllength=360;}break;
264 case DES_NTSCSELTINT:if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=2;controllength=360;}break;
267 if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF)
274 which=controlselect==1?ntschue:ntsctint;
287 if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF)
292 switch(controlselect)
295 if(ntschue>128) ntschue=128;
299 if(ntsctint>128) ntsctint=128;
312 static uint8 lastd=0;
313 void SetNESDeemph(uint8 d, int force)
315 static uint16 rtmul[7]={32768*1.239,32768*.794,32768*1.019,32768*.905,32768*1.023,32768*.741,32768*.75};
316 static uint16 gtmul[7]={32768*.915,32768*1.086,32768*.98,32768*1.026,32768*.908,32768*.987,32768*.75};
317 static uint16 btmul[7]={32768*.743,32768*.882,32768*.653,32768*1.277,32768*.979,32768*.101,32768*.75};
321 /* If it's not forced(only forced when the palette changes),
322 don't waste cpu time if the same deemphasis bits are set as the last call.
329 else /* Only set this when palette has changed. */
347 FCEUD_SetPalette(x|0x40,m,n,o);
352 if(!d) return; /* No deemphasis, so return. */
372 FCEUD_SetPalette(x|0xC0,m,n,o);
379 #define HUEVAL ((double)((double)ntschue/(double)2)+(double)300)
380 #define TINTVAL ((double)((double)ntsctint/(double)128))
382 static void CalculatePalette(void)
387 static uint8 cols[16]={0,24,21,18,15,12,9,6,3,0,33,30,27,0,0,0};
388 static uint8 br1[4]={6,9,12,12};
389 static double br2[4]={.29,.45,.73,.9};
390 static double br3[4]={0,.24,.47,.77};
397 if(z==0) {s=0;y=((double)br1[x])/12;}
406 theta=(double)M_PI*(double)(((double)cols[z]*10+HUEVAL)/(double)180);
407 r=(int)(((double)y+(double)s*(double)sin(theta))*(double)256);
408 g=(int)(((double)y-(double)((double)27/(double)53)*s*(double)sin(theta)+(double)((double)10/(double)53)*s*cos(theta))*(double)256);
409 b=(int)(((double)y-(double)s*(double)cos(theta))*(double)256);
411 // TODO: Fix RGB to compensate for phosphor changes(add to red??).
420 paletten[(x<<4)+z].r=r;
421 paletten[(x<<4)+z].g=g;
422 paletten[(x<<4)+z].b=b;
430 void FCEU_PutImageDummy(void)
432 if(FCEUGameInfo.type!=GIT_NSF)
434 if(controllength) controllength--;
436 if(StateShow) StateShow--; /* DrawState() */
437 if(howlong) howlong--; /* DrawMessage() */
440 extern uint64 frcount;
448 void FCEU_PutImage(void)
450 if(FCEUGameInfo.type==GIT_NSF)
453 /* Save snapshot after NSF screen is drawn. Why would we want to
464 /* Save snapshot before overlay stuff is written. */
470 if(FCEUGameInfo.type==GIT_VSUNI)
471 FCEU_VSUniDraw(XBuf);
472 //if(StateShow) DrawState();
474 //FCEU_DrawSaveStates(XBuf);
475 //FCEU_DrawMovies(XBuf);
476 //FCEU_DrawNTSCControlBars(XBuf);
477 //FCEU_DrawRecordingStatus(XBuf);
479 //if(controllength) {controllength--;DrawBars();}
484 extern uint64 frcount;
492 static int ipalette=0;
494 void LoadGamePalette(void)
499 if((fp=fopen(FCEU_MakeFName(FCEUMKF_PALETTE,0,0),"rb")))
502 fread(ptmp,1,192,fp);
506 palettei[x].r=ptmp[x+x+x];
507 palettei[x].g=ptmp[x+x+x+1];
508 palettei[x].b=ptmp[x+x+x+2];
514 void FCEU_ResetPalette(void)
520 static void ChoosePalette(void)
522 if(FCEUGameInfo.type==GIT_NSF)
526 else if(ntsccol && !PAL && FCEUGameInfo.type!=GIT_VSUNI)
535 void WritePalette(void)
540 FCEUD_SetPalette(x+128,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);
541 if(FCEUGameInfo.type==GIT_NSF)
544 FCEUD_SetPalette(x,palo[x].r,palo[x].g,palo[x].b);
549 FCEUD_SetPalette(x,palo[x].r,palo[x].g,palo[x].b);
550 SetNESDeemph(lastd,1);
554 void FlushCommandQueue(void)
556 if(!netplay && CommandQueue) {DoCommand(CommandQueue);CommandQueue=0;}
559 void DoCommand(uint8 c)
563 case 1:FDSControl(FDS_SELECT);break;
564 case 2:FDSControl(FDS_IDISK);break;
565 case 3:FDSControl(FDS_EJECT);break;
567 case 10:DIPS^=2;break;
568 case 11:vsdip^=1;DIPS|=2;break;
569 case 12:vsdip^=2;DIPS|=2;break;
570 case 13:vsdip^=4;DIPS|=2;break;
571 case 14:vsdip^=8;DIPS|=2;break;
572 case 15:vsdip^=0x10;DIPS|=2;break;
573 case 16:vsdip^=0x20;DIPS|=2;break;
574 case 17:vsdip^=0x40;DIPS|=2;break;
575 case 18:vsdip^=0x80;DIPS|=2;break;
576 case 19:coinon=6;break;
577 case 30:ResetNES();break;
578 case 31:PowerNES();break;
579 case 40:CheckStates();StateShow=0;SaveState();break;
580 case 41:CheckStates();StateShow=0;LoadState();break;
581 case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49:
582 case 50: case 51:StateShow=180;CurrentState=c-42;CheckStates();break;