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