92764e62 |
1 | /* FCE Ultra - NES/Famicom Emulator\r |
2 | *\r |
3 | * Copyright notice for this file:\r |
4 | * Copyright (C) 2002,2003 Xodnizel\r |
5 | *\r |
6 | * This program is free software; you can redistribute it and/or modify\r |
7 | * it under the terms of the GNU General Public License as published by\r |
8 | * the Free Software Foundation; either version 2 of the License, or\r |
9 | * (at your option) any later version.\r |
10 | *\r |
11 | * This program is distributed in the hope that it will be useful,\r |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of\r |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r |
14 | * GNU General Public License for more details.\r |
15 | *\r |
16 | * You should have received a copy of the GNU General Public License\r |
17 | * along with this program; if not, write to the Free Software\r |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r |
19 | */\r |
20 | \r |
21 | #include <stdio.h>\r |
22 | #include <stdlib.h>\r |
23 | #include <math.h>\r |
24 | \r |
25 | #include "types.h"\r |
26 | #include "fce.h"\r |
27 | #include "general.h"\r |
28 | #include "driver.h"\r |
29 | \r |
30 | #include "palette.h"\r |
31 | #include "palettes/palettes.h"\r |
32 | \r |
33 | #include "svga.h"\r |
34 | \r |
35 | #ifndef M_PI\r |
36 | #define M_PI 3.14159265358979323846\r |
37 | #endif\r |
38 | \r |
39 | static int ntsccol=0;\r |
40 | static int ntsctint=46+10;\r |
41 | static int ntschue=72;\r |
42 | \r |
43 | /* These are dynamically filled/generated palettes: */\r |
44 | pal palettei[64]; // Custom palette for an individual game.\r |
45 | pal palettec[64]; // Custom "global" palette.\r |
46 | pal paletten[64]; // Mathematically generated palette.\r |
47 | \r |
48 | static void CalculatePalette(void);\r |
49 | static void ChoosePalette(void);\r |
50 | static void WritePalette(void);\r |
51 | uint8 pale=0;\r |
52 | \r |
53 | pal *palo;\r |
54 | static pal *palpoint[8]=\r |
55 | {\r |
56 | palette,\r |
57 | rp2c04001,\r |
58 | rp2c04002,\r |
59 | rp2c04003,\r |
60 | rp2c05004,\r |
61 | };\r |
62 | \r |
63 | void FCEUI_SetPaletteArray(uint8 *pal)\r |
64 | {\r |
65 | if(!pal)\r |
66 | palpoint[0]=palette;\r |
67 | else\r |
68 | {\r |
69 | int x;\r |
70 | palpoint[0]=palettec;\r |
71 | for(x=0;x<64;x++)\r |
72 | {\r |
73 | palpoint[0][x].r=*((uint8 *)pal+x+x+x);\r |
74 | palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);\r |
75 | palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);\r |
76 | }\r |
77 | }\r |
78 | FCEU_ResetPalette();\r |
79 | }\r |
80 | \r |
81 | \r |
82 | void FCEUI_SetNTSCTH(int n, int tint, int hue)\r |
83 | {\r |
84 | ntsctint=tint;\r |
85 | ntschue=hue;\r |
86 | ntsccol=n;\r |
87 | FCEU_ResetPalette();\r |
88 | }\r |
89 | \r |
90 | static uint8 lastd=0;\r |
91 | void SetNESDeemph(uint8 d, int force)\r |
92 | {\r |
93 | static uint16 rtmul[7]={32768*1.239,32768*.794,32768*1.019,32768*.905,32768*1.023,32768*.741,32768*.75};\r |
94 | static uint16 gtmul[7]={32768*.915,32768*1.086,32768*.98,32768*1.026,32768*.908,32768*.987,32768*.75};\r |
95 | static uint16 btmul[7]={32768*.743,32768*.882,32768*.653,32768*1.277,32768*.979,32768*.101,32768*.75};\r |
96 | uint32 r,g,b;\r |
97 | int x;\r |
98 | \r |
99 | /* If it's not forced(only forced when the palette changes),\r |
100 | don't waste cpu time if the same deemphasis bits are set as the last call.\r |
101 | */\r |
102 | if(!force)\r |
103 | {\r |
104 | if(d==lastd)\r |
105 | return;\r |
106 | }\r |
107 | else /* Only set this when palette has changed. */\r |
108 | {\r |
109 | r=rtmul[6];\r |
110 | g=rtmul[6];\r |
111 | b=rtmul[6];\r |
112 | \r |
113 | for(x=0;x<0x40;x++)\r |
114 | {\r |
115 | uint32 m,n,o;\r |
116 | m=palo[x].r;\r |
117 | n=palo[x].g;\r |
118 | o=palo[x].b;\r |
119 | m=(m*r)>>15;\r |
120 | n=(n*g)>>15;\r |
121 | o=(o*b)>>15;\r |
122 | if(m>0xff) m=0xff;\r |
123 | if(n>0xff) n=0xff;\r |
124 | if(o>0xff) o=0xff;\r |
125 | FCEUD_SetPalette(x|0xC0,m,n,o);\r |
126 | }\r |
127 | }\r |
128 | if(!d) return; /* No deemphasis, so return. */\r |
129 | \r |
130 | r=rtmul[d-1];\r |
131 | g=gtmul[d-1];\r |
132 | b=btmul[d-1];\r |
133 | \r |
134 | for(x=0;x<0x40;x++)\r |
135 | {\r |
136 | uint32 m,n,o;\r |
137 | \r |
138 | m=palo[x].r;\r |
139 | n=palo[x].g;\r |
140 | o=palo[x].b;\r |
141 | m=(m*r)>>15;\r |
142 | n=(n*g)>>15;\r |
143 | o=(o*b)>>15;\r |
144 | if(m>0xff) m=0xff;\r |
145 | if(n>0xff) n=0xff;\r |
146 | if(o>0xff) o=0xff;\r |
147 | \r |
148 | FCEUD_SetPalette(x|0x40,m,n,o);\r |
149 | }\r |
150 | \r |
151 | lastd=d;\r |
152 | }\r |
153 | \r |
154 | /* Converted from Kevin Horton's qbasic palette generator. */\r |
155 | static void CalculatePalette(void)\r |
156 | {\r |
157 | int x,z;\r |
158 | int r,g,b;\r |
159 | double s,luma,theta;\r |
160 | static uint8 cols[16]={0,24,21,18,15,12,9,6,3,0,33,30,27,0,0,0};\r |
161 | static uint8 br1[4]={6,9,12,12};\r |
162 | static double br2[4]={.29,.45,.73,.9};\r |
163 | static double br3[4]={0,.24,.47,.77};\r |
164 | \r |
165 | for(x=0;x<=3;x++)\r |
166 | for(z=0;z<16;z++)\r |
167 | {\r |
168 | s=(double)ntsctint/128;\r |
169 | luma=br2[x];\r |
170 | if(z==0) {s=0;luma=((double)br1[x])/12;}\r |
171 | \r |
172 | if(z>=13)\r |
173 | {\r |
174 | s=luma=0;\r |
175 | if(z==13)\r |
176 | luma=br3[x];\r |
177 | }\r |
178 | \r |
179 | theta=(double)M_PI*(double)(((double)cols[z]*10+ (((double)ntschue/2)+300) )/(double)180);\r |
180 | r=(int)((luma+s*sin(theta))*256);\r |
181 | g=(int)((luma-(double)27/53*s*sin(theta)+(double)10/53*s*cos(theta))*256);\r |
182 | b=(int)((luma-s*cos(theta))*256);\r |
183 | \r |
184 | \r |
185 | if(r>255) r=255;\r |
186 | if(g>255) g=255;\r |
187 | if(b>255) b=255;\r |
188 | if(r<0) r=0;\r |
189 | if(g<0) g=0;\r |
190 | if(b<0) b=0;\r |
191 | \r |
192 | paletten[(x<<4)+z].r=r;\r |
193 | paletten[(x<<4)+z].g=g;\r |
194 | paletten[(x<<4)+z].b=b;\r |
195 | }\r |
196 | WritePalette();\r |
197 | }\r |
198 | \r |
199 | static int ipalette=0;\r |
200 | \r |
201 | void FCEU_LoadGamePalette(void)\r |
202 | {\r |
203 | uint8 ptmp[192];\r |
204 | FILE *fp;\r |
205 | char *fn;\r |
206 | \r |
207 | ipalette=0;\r |
208 | \r |
209 | fn=FCEU_MakeFName(FCEUMKF_PALETTE,0,0);\r |
210 | \r |
211 | if((fp=fopen(fn,"rb")))\r |
212 | {\r |
213 | int x;\r |
214 | fread(ptmp,1,192,fp);\r |
215 | fclose(fp);\r |
216 | for(x=0;x<64;x++)\r |
217 | {\r |
218 | palettei[x].r=ptmp[x+x+x];\r |
219 | palettei[x].g=ptmp[x+x+x+1];\r |
220 | palettei[x].b=ptmp[x+x+x+2];\r |
221 | }\r |
222 | ipalette=1;\r |
223 | }\r |
224 | free(fn);\r |
225 | }\r |
226 | \r |
227 | void FCEU_ResetPalette(void)\r |
228 | {\r |
229 | //if(FCEUGameInfo)\r |
230 | {\r |
231 | ChoosePalette();\r |
232 | WritePalette();\r |
233 | }\r |
234 | }\r |
235 | \r |
236 | static void ChoosePalette(void)\r |
237 | {\r |
238 | if(FCEUGameInfo.type==GIT_NSF)\r |
239 | palo=0;\r |
240 | else if(ipalette)\r |
241 | palo=palettei;\r |
242 | else if(ntsccol && !PAL && FCEUGameInfo.type!=GIT_VSUNI)\r |
243 | {\r |
244 | palo=paletten;\r |
245 | CalculatePalette();\r |
246 | }\r |
247 | else\r |
248 | palo=palpoint[pale];\r |
249 | }\r |
250 | \r |
251 | void WritePalette(void)\r |
252 | {\r |
253 | int x;\r |
254 | \r |
255 | for(x=0;x<7;x++)\r |
6587f346 |
256 | FCEUD_SetPalette(x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);\r |
92764e62 |
257 | if(FCEUGameInfo.type==GIT_NSF)\r |
258 | {\r |
259 | //for(x=0;x<128;x++)\r |
260 | // FCEUD_SetPalette(x,x,0,x);\r |
92764e62 |
261 | }\r |
262 | else\r |
263 | {\r |
264 | for(x=0;x<64;x++)\r |
6587f346 |
265 | FCEUD_SetPalette(x+128,palo[x].r,palo[x].g,palo[x].b);\r |
92764e62 |
266 | SetNESDeemph(lastd,1);\r |
267 | }\r |
268 | }\r |
269 | \r |
270 | void FCEUI_GetNTSCTH(int *tint, int *hue)\r |
271 | {\r |
272 | *tint=ntsctint;\r |
273 | *hue=ntschue;\r |
274 | }\r |
275 | \r |
276 | static int controlselect=0;\r |
277 | static int controllength=0;\r |
278 | \r |
279 | void FCEUI_NTSCDEC(void)\r |
280 | {\r |
281 | if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI &&!PAL && FCEUGameInfo.type!=GIT_NSF)\r |
282 | {\r |
283 | int which;\r |
284 | if(controlselect)\r |
285 | {\r |
286 | if(controllength)\r |
287 | {\r |
288 | which=controlselect==1?ntschue:ntsctint;\r |
289 | which--;\r |
290 | if(which<0) which=0;\r |
291 | if(controlselect==1)\r |
292 | ntschue=which;\r |
293 | else ntsctint=which;\r |
294 | CalculatePalette();\r |
295 | }\r |
296 | controllength=360;\r |
297 | }\r |
298 | }\r |
299 | }\r |
300 | \r |
301 | void FCEUI_NTSCINC(void)\r |
302 | {\r |
303 | if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF)\r |
304 | if(controlselect)\r |
305 | {\r |
306 | if(controllength)\r |
307 | {\r |
308 | switch(controlselect)\r |
309 | {\r |
310 | case 1:ntschue++;\r |
311 | if(ntschue>128) ntschue=128;\r |
312 | CalculatePalette();\r |
313 | break;\r |
314 | case 2:ntsctint++;\r |
315 | if(ntsctint>128) ntsctint=128;\r |
316 | CalculatePalette();\r |
317 | break;\r |
318 | }\r |
319 | }\r |
320 | controllength=360;\r |
321 | }\r |
322 | }\r |
323 | \r |
324 | void FCEUI_NTSCSELHUE(void)\r |
325 | {\r |
326 | if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=1;controllength=360;}\r |
327 | }\r |
328 | \r |
329 | void FCEUI_NTSCSELTINT(void)\r |
330 | {\r |
331 | if(ntsccol && FCEUGameInfo.type!=GIT_VSUNI && !PAL && FCEUGameInfo.type!=GIT_NSF){controlselect=2;controllength=360;}\r |
332 | }\r |
333 | \r |
334 | void FCEU_DrawNTSCControlBars(uint8 *XBuf)\r |
335 | {\r |
336 | uint8 *XBaf;\r |
337 | int which=0;\r |
338 | int x,x2;\r |
339 | \r |
340 | if(!controllength) return;\r |
341 | controllength--;\r |
342 | if(!XBuf) return;\r |
343 | \r |
344 | if(controlselect==1)\r |
345 | {\r |
346 | DrawTextTrans(XBuf+128-12+180*256, 256, (uint8 *)"Hue", 0x85);\r |
347 | which=ntschue<<1;\r |
348 | }\r |
349 | else if(controlselect==2)\r |
350 | {\r |
351 | DrawTextTrans(XBuf+128-16+180*256, 256, (uint8 *)"Tint", 0x85);\r |
352 | which=ntsctint<<1;\r |
353 | }\r |
354 | \r |
355 | XBaf=XBuf+200*256;\r |
356 | for(x=0;x<which;x+=2)\r |
357 | {\r |
358 | for(x2=6;x2>=-6;x2--)\r |
359 | {\r |
360 | XBaf[x-256*x2]=0x85;\r |
361 | }\r |
362 | }\r |
363 | for(;x<256;x+=2)\r |
364 | {\r |
365 | for(x2=2;x2>=-2;x2--)\r |
366 | XBaf[x-256*x2]=0x85;\r |
367 | }\r |
368 | }\r |