--- /dev/null
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ * Copyright (C) 2002,2003 Xodnizel\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <math.h>\r
+\r
+#include "types.h"\r
+#include "fce.h"\r
+#include "general.h"\r
+#include "driver.h"\r
+\r
+#include "palette.h"\r
+#include "palettes/palettes.h"\r
+\r
+#include "svga.h"\r
+\r
+#ifndef M_PI\r
+#define M_PI 3.14159265358979323846\r
+#endif\r
+\r
+static int ntsccol=0;\r
+static int ntsctint=46+10;\r
+static int ntschue=72;\r
+\r
+/* These are dynamically filled/generated palettes: */\r
+pal palettei[64]; // Custom palette for an individual game.\r
+pal palettec[64]; // Custom "global" palette.\r
+pal paletten[64]; // Mathematically generated palette.\r
+\r
+static void CalculatePalette(void);\r
+static void ChoosePalette(void);\r
+static void WritePalette(void);\r
+uint8 pale=0;\r
+\r
+pal *palo;\r
+static pal *palpoint[8]=\r
+ {\r
+ palette,\r
+ rp2c04001,\r
+ rp2c04002,\r
+ rp2c04003,\r
+ rp2c05004,\r
+ };\r
+\r
+void FCEUI_SetPaletteArray(uint8 *pal)\r
+{\r
+ if(!pal)\r
+ palpoint[0]=palette;\r
+ else\r
+ {\r
+ int x;\r
+ palpoint[0]=palettec;\r
+ for(x=0;x<64;x++)\r
+ {\r
+ palpoint[0][x].r=*((uint8 *)pal+x+x+x);\r
+ palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);\r
+ palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);\r
+ }\r
+ }\r
+ FCEU_ResetPalette();\r
+}\r
+\r
+\r
+void FCEUI_SetNTSCTH(int n, int tint, int hue)\r
+{\r
+ ntsctint=tint;\r
+ ntschue=hue;\r
+ ntsccol=n;\r
+ FCEU_ResetPalette();\r
+}\r
+\r
+static uint8 lastd=0;\r
+void SetNESDeemph(uint8 d, int force)\r
+{\r
+ static uint16 rtmul[7]={32768*1.239,32768*.794,32768*1.019,32768*.905,32768*1.023,32768*.741,32768*.75};\r
+ static uint16 gtmul[7]={32768*.915,32768*1.086,32768*.98,32768*1.026,32768*.908,32768*.987,32768*.75};\r
+ static uint16 btmul[7]={32768*.743,32768*.882,32768*.653,32768*1.277,32768*.979,32768*.101,32768*.75};\r
+ uint32 r,g,b;\r
+ int x;\r
+\r
+ /* If it's not forced(only forced when the palette changes),\r
+ don't waste cpu time if the same deemphasis bits are set as the last call.\r
+ */\r
+ if(!force)\r
+ {\r
+ if(d==lastd)\r
+ return;\r
+ }\r
+ else /* Only set this when palette has changed. */\r
+ {\r
+ r=rtmul[6];\r
+ g=rtmul[6];\r
+ b=rtmul[6];\r
+\r
+ for(x=0;x<0x40;x++)\r
+ {\r
+ uint32 m,n,o;\r
+ m=palo[x].r;\r
+ n=palo[x].g;\r
+ o=palo[x].b;\r
+ m=(m*r)>>15;\r
+ n=(n*g)>>15;\r
+ o=(o*b)>>15;\r
+ if(m>0xff) m=0xff;\r
+ if(n>0xff) n=0xff;\r
+ if(o>0xff) o=0xff;\r
+ FCEUD_SetPalette(x|0xC0,m,n,o);\r
+ }\r
+ }\r
+ if(!d) return; /* No deemphasis, so return. */\r
+\r
+ r=rtmul[d-1];\r
+ g=gtmul[d-1];\r
+ b=btmul[d-1];\r
+\r
+ for(x=0;x<0x40;x++)\r
+ {\r
+ uint32 m,n,o;\r
+\r
+ m=palo[x].r;\r
+ n=palo[x].g;\r
+ o=palo[x].b;\r
+ m=(m*r)>>15;\r
+ n=(n*g)>>15;\r
+ o=(o*b)>>15;\r
+ if(m>0xff) m=0xff;\r
+ if(n>0xff) n=0xff;\r
+ if(o>0xff) o=0xff;\r
+\r
+ FCEUD_SetPalette(x|0x40,m,n,o);\r
+ }\r
+\r
+ lastd=d;\r
+}\r
+\r
+/* Converted from Kevin Horton's qbasic palette generator. */\r
+static void CalculatePalette(void)\r
+{\r
+ int x,z;\r
+ int r,g,b;\r
+ double s,luma,theta;\r
+ static uint8 cols[16]={0,24,21,18,15,12,9,6,3,0,33,30,27,0,0,0};\r
+ static uint8 br1[4]={6,9,12,12};\r
+ static double br2[4]={.29,.45,.73,.9};\r
+ static double br3[4]={0,.24,.47,.77};\r
+\r
+ for(x=0;x<=3;x++)\r
+ for(z=0;z<16;z++)\r
+ {\r
+ s=(double)ntsctint/128;\r
+ luma=br2[x];\r
+ if(z==0) {s=0;luma=((double)br1[x])/12;}\r
+\r
+ if(z>=13)\r
+ {\r
+ s=luma=0;\r
+ if(z==13)\r
+ luma=br3[x];\r
+ }\r
+\r
+ theta=(double)M_PI*(double)(((double)cols[z]*10+ (((double)ntschue/2)+300) )/(double)180);\r
+ r=(int)((luma+s*sin(theta))*256);\r
+ g=(int)((luma-(double)27/53*s*sin(theta)+(double)10/53*s*cos(theta))*256);\r
+ b=(int)((luma-s*cos(theta))*256);\r
+\r
+\r
+ if(r>255) r=255;\r
+ if(g>255) g=255;\r
+ if(b>255) b=255;\r
+ if(r<0) r=0;\r
+ if(g<0) g=0;\r
+ if(b<0) b=0;\r
+\r
+ paletten[(x<<4)+z].r=r;\r
+ paletten[(x<<4)+z].g=g;\r
+ paletten[(x<<4)+z].b=b;\r
+ }\r
+ WritePalette();\r
+}\r
+\r
+static int ipalette=0;\r
+\r
+void FCEU_LoadGamePalette(void)\r
+{\r
+ uint8 ptmp[192];\r
+ FILE *fp;\r
+ char *fn;\r
+\r
+ ipalette=0;\r
+\r
+ fn=FCEU_MakeFName(FCEUMKF_PALETTE,0,0);\r
+\r
+ if((fp=fopen(fn,"rb")))\r
+ {\r
+ int x;\r
+ fread(ptmp,1,192,fp);\r
+ fclose(fp);\r
+ for(x=0;x<64;x++)\r
+ {\r
+ palettei[x].r=ptmp[x+x+x];\r
+ palettei[x].g=ptmp[x+x+x+1];\r
+ palettei[x].b=ptmp[x+x+x+2];\r
+ }\r
+ ipalette=1;\r
+ }\r
+ free(fn);\r
+}\r
+\r
+void FCEU_ResetPalette(void)\r
+{\r
+ //if(FCEUGameInfo)\r
+ {\r
+ ChoosePalette();\r
+ WritePalette();\r
+ }\r
+}\r
+\r
+static void ChoosePalette(void)\r
+{\r
+ if(FCEUGameInfo.type==GIT_NSF)\r
+ palo=0;\r
+ else if(ipalette)\r
+ palo=palettei;\r
+ else if(ntsccol && !PAL && FCEUGameInfo.type!=GIT_VSUNI)\r
+ {\r
+ palo=paletten;\r
+ CalculatePalette();\r
+ }\r
+ else\r
+ palo=palpoint[pale];\r
+}\r
+\r
+void WritePalette(void)\r
+{\r
+ int x;\r
+\r
+ for(x=0;x<7;x++)\r
+ FCEUD_SetPalette(128+x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);\r
+ if(FCEUGameInfo.type==GIT_NSF)\r
+ {\r
+ //for(x=0;x<128;x++)\r
+ // FCEUD_SetPalette(x,x,0,x);\r
+ for(x=0;x<7;x++)\r
+ FCEUD_SetPalette(x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);\r
+ }\r
+ else\r
+ {\r
+ for(x=0;x<64;x++)\r
+ FCEUD_SetPalette(x,palo[x].r,palo[x].g,palo[x].b);\r
+ SetNESDeemph(lastd,1);\r
+ }\r
+}\r
+\r
+void FCEUI_GetNTSCTH(int *tint, int *hue)\r
+{\r
+ *tint=ntsctint;\r
+ *hue=ntschue;\r
+}\r
+\r
+static int controlselect=0;\r
+static int controllength=0;\r
+\r
+void FCEUI_NTSCDEC(void)\r
+{\r
+ if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI &&!PAL && FCEUGameInfo.type!=GIT_NSF)\r
+ {\r
+ int which;\r
+ if(controlselect)\r
+ {\r
+ if(controllength)\r
+ {\r
+ which=controlselect==1?ntschue:ntsctint;\r
+ which--;\r
+ if(which<0) which=0;\r
+ if(controlselect==1)\r
+ ntschue=which;\r
+ else ntsctint=which;\r
+ CalculatePalette();\r
+ }\r
+ controllength=360;\r
+ }\r
+ }\r
+}\r
+\r
+void FCEUI_NTSCINC(void)\r
+{\r
+ if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF)\r
+ if(controlselect)\r
+ {\r
+ if(controllength)\r
+ {\r
+ switch(controlselect)\r
+ {\r
+ case 1:ntschue++;\r
+ if(ntschue>128) ntschue=128;\r
+ CalculatePalette();\r
+ break;\r
+ case 2:ntsctint++;\r
+ if(ntsctint>128) ntsctint=128;\r
+ CalculatePalette();\r
+ break;\r
+ }\r
+ }\r
+ controllength=360;\r
+ }\r
+}\r
+\r
+void FCEUI_NTSCSELHUE(void)\r
+{\r
+ if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=1;controllength=360;}\r
+}\r
+\r
+void FCEUI_NTSCSELTINT(void)\r
+{\r
+ if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=2;controllength=360;}\r
+}\r
+\r
+void FCEU_DrawNTSCControlBars(uint8 *XBuf)\r
+{\r
+ uint8 *XBaf;\r
+ int which=0;\r
+ int x,x2;\r
+\r
+ if(!controllength) return;\r
+ controllength--;\r
+ if(!XBuf) return;\r
+\r
+ if(controlselect==1)\r
+ {\r
+ DrawTextTrans(XBuf+128-12+180*256, 256, (uint8 *)"Hue", 0x85);\r
+ which=ntschue<<1;\r
+ }\r
+ else if(controlselect==2)\r
+ {\r
+ DrawTextTrans(XBuf+128-16+180*256, 256, (uint8 *)"Tint", 0x85);\r
+ which=ntsctint<<1;\r
+ }\r
+\r
+ XBaf=XBuf+200*256;\r
+ for(x=0;x<which;x+=2)\r
+ {\r
+ for(x2=6;x2>=-6;x2--)\r
+ {\r
+ XBaf[x-256*x2]=0x85;\r
+ }\r
+ }\r
+ for(;x<256;x+=2)\r
+ {\r
+ for(x2=2;x2>=-2;x2--)\r
+ XBaf[x-256*x2]=0x85;\r
+ }\r
+}\r