328 lines
7.6 KiB
C
328 lines
7.6 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "fceu-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
|
|
|
|
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,
|
|
rp2c04_0001,
|
|
rp2c04_0002,
|
|
rp2c04_0003,
|
|
rp2c04_0004,
|
|
rp2c03,
|
|
};
|
|
|
|
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();
|
|
}
|
|
|
|
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 (GameInfo) {
|
|
ChoosePalette();
|
|
WritePalette();
|
|
}
|
|
}
|
|
|
|
static void ChoosePalette(void) {
|
|
if (GameInfo->type == GIT_NSF)
|
|
palo = 0;
|
|
else if (ipalette)
|
|
palo = palettei;
|
|
else if (ntsccol && !PAL && GameInfo->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 (GameInfo->type == GIT_NSF) {
|
|
} 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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF) {
|
|
controlselect = 1; controllength = 360;
|
|
}
|
|
}
|
|
|
|
void FCEUI_NTSCSELTINT(void) {
|
|
if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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;
|
|
}
|
|
}
|