Merge nsf.c

This commit is contained in:
twinaphex 2015-08-06 13:08:03 +02:00
parent 432126f3ee
commit f40df99fe1
2 changed files with 1 additions and 520 deletions

View File

@ -1,519 +0,0 @@
/* FCE Ultra - NES/Famicom Emulator
*
* Copyright notice for this file:
* Copyright (C) 2002 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 <string.h>
#include <math.h>
#include "fceu-types.h"
#include "x6502.h"
#include "fceu.h"
#include "video.h"
#include "sound.h"
#include "nsf.h"
#include "general.h"
#include "fceu-memory.h"
#include "file.h"
#include "fds.h"
#include "cart.h"
#include "input.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static uint8 SongReload;
static int CurrentSong;
static DECLFW(NSF_write);
static DECLFR(NSF_read);
static int vismode = 1;
static uint8 NSFROM[0x30 + 6] =
{
/* 0x00 - NMI */
0x8D, 0xF4, 0x3F, /* Stop play routine NMIs. */
0xA2, 0xFF, 0x9A, /* Initialize the stack pointer. */
0xAD, 0xF0, 0x3F, /* See if we need to init. */
0xF0, 0x09, /* If 0, go to play routine playing. */
0xAD, 0xF1, 0x3F, /* Confirm and load A */
0xAE, 0xF3, 0x3F, /* Load X with PAL/NTSC byte */
0x20, 0x00, 0x00, /* JSR to init routine */
0xA9, 0x00,
0xAA,
0xA8,
0x20, 0x00, 0x00, /* JSR to play routine */
0x8D, 0xF5, 0x3F, /* Start play routine NMIs. */
0x90, 0xFE, /* Loopie time. */
/* 0x20 */
0x8D, 0xF3, 0x3F, /* Init init NMIs */
0x18,
0x90, 0xFE /* Loopie time. */
};
static DECLFR(NSFROMRead) {
return (NSFROM - 0x3800)[A];
}
static int doreset = 0;
static int NSFNMIFlags;
static uint8 *NSFDATA = 0;
static int NSFMaxBank;
static int NSFSize;
static uint8 BSon;
static uint16 PlayAddr;
static uint16 InitAddr;
static uint16 LoadAddr;
static NSF_HEADER NSFHeader;
void NSFMMC5_Close(void);
static uint8 *ExWRAM = 0;
void NSFGI(int h) {
switch (h) {
case GI_CLOSE:
if (NSFDATA) {
free(NSFDATA); NSFDATA = 0;
}
if (ExWRAM) {
free(ExWRAM); ExWRAM = 0;
}
if (NSFHeader.SoundChip & 1) {
// NSFVRC6_Init();
} else if (NSFHeader.SoundChip & 2) {
// NSFVRC7_Init();
} else if (NSFHeader.SoundChip & 4) {
// FDSSoundReset();
} else if (NSFHeader.SoundChip & 8) {
NSFMMC5_Close();
} else if (NSFHeader.SoundChip & 0x10) {
// NSFN106_Init();
} else if (NSFHeader.SoundChip & 0x20) {
// NSFAY_Init();
}
break;
case GI_RESETM2:
case GI_POWER: NSF_init(); break;
}
}
// First 32KB is reserved for sound chip emulation in the iNES mapper code.
static INLINE void BANKSET(uint32 A, uint32 bank) {
bank &= NSFMaxBank;
if (NSFHeader.SoundChip & 4)
memcpy(ExWRAM + (A - 0x6000), NSFDATA + (bank << 12), 4096);
else
setprg4(A, bank);
}
int NSFLoad(FCEUFILE *fp) {
int x;
FCEU_fseek(fp, 0, SEEK_SET);
FCEU_fread(&NSFHeader, 1, 0x80, fp);
if (memcmp(NSFHeader.ID, "NESM\x1a", 5))
return 0;
NSFHeader.SongName[31] = NSFHeader.Artist[31] = NSFHeader.Copyright[31] = 0;
LoadAddr = NSFHeader.LoadAddressLow;
LoadAddr |= NSFHeader.LoadAddressHigh << 8;
if (LoadAddr < 0x6000) {
FCEUD_PrintError("Invalid load address.");
return(0);
}
InitAddr = NSFHeader.InitAddressLow;
InitAddr |= NSFHeader.InitAddressHigh << 8;
PlayAddr = NSFHeader.PlayAddressLow;
PlayAddr |= NSFHeader.PlayAddressHigh << 8;
NSFSize = FCEU_fgetsize(fp) - 0x80;
NSFMaxBank = ((NSFSize + (LoadAddr & 0xfff) + 4095) / 4096);
NSFMaxBank = uppow2(NSFMaxBank);
if (!(NSFDATA = (uint8*)FCEU_malloc(NSFMaxBank * 4096)))
return 0;
FCEU_fseek(fp, 0x80, SEEK_SET);
memset(NSFDATA, 0x00, NSFMaxBank * 4096);
FCEU_fread(NSFDATA + (LoadAddr & 0xfff), 1, NSFSize, fp);
NSFMaxBank--;
BSon = 0;
for (x = 0; x < 8; x++)
BSon |= NSFHeader.BankSwitch[x];
GameInfo->type = GIT_NSF;
GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD;
GameInfo->cspecial = SIS_NSF;
for (x = 0;; x++) {
if (NSFROM[x] == 0x20) {
NSFROM[x + 1] = InitAddr & 0xFF;
NSFROM[x + 2] = InitAddr >> 8;
NSFROM[x + 8] = PlayAddr & 0xFF;
NSFROM[x + 9] = PlayAddr >> 8;
break;
}
}
if (NSFHeader.VideoSystem == 0)
GameInfo->vidsys = GIV_NTSC;
else if (NSFHeader.VideoSystem == 1)
GameInfo->vidsys = GIV_PAL;
GameInterface = NSFGI;
FCEU_printf("NSF Loaded. File information:\n\n");
FCEU_printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n", NSFHeader.SongName, NSFHeader.Artist, NSFHeader.Copyright);
if (NSFHeader.SoundChip) {
static char *tab[6] = { "Konami VRCVI", "Konami VRCVII", "Nintendo FDS", "Nintendo MMC5", "Namco 106", "Sunsoft FME-07" };
for (x = 0; x < 6; x++)
if (NSFHeader.SoundChip & (1 << x)) {
FCEU_printf(" Expansion hardware: %s\n", tab[x]);
NSFHeader.SoundChip = 1 << x; /* Prevent confusing weirdness if more than one bit is set. */
break;
}
}
if (BSon)
FCEU_printf(" Bank-switched.\n");
FCEU_printf(" Load address: $%04x\n Init address: $%04x\n Play address: $%04x\n", LoadAddr, InitAddr, PlayAddr);
FCEU_printf(" %s\n", (NSFHeader.VideoSystem & 1) ? "PAL" : "NTSC");
FCEU_printf(" Starting song: %d / %d\n\n", NSFHeader.StartingSong, NSFHeader.TotalSongs);
if (NSFHeader.SoundChip & 4)
ExWRAM = FCEU_gmalloc(32768 + 8192);
else
ExWRAM = FCEU_gmalloc(8192);
return 1;
}
static DECLFR(NSFVectorRead) {
if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2) || doreset) {
if (A == 0xFFFA) return(0x00);
else if (A == 0xFFFB) return(0x38);
else if (A == 0xFFFC) return(0x20);
else if (A == 0xFFFD) {
doreset = 0; return(0x38);
}
return(X.DB);
} else
return(CartBR(A));
}
void NSFVRC6_Init(void);
void NSFVRC7_Init(void);
void NSFMMC5_Init(void);
void NSFN106_Init(void);
void NSFAY_Init(void);
void NSF_init(void) {
doreset = 1;
ResetCartMapping();
if (NSFHeader.SoundChip & 4) {
SetupCartPRGMapping(0, ExWRAM, 32768 + 8192, 1);
setprg32(0x6000, 0);
setprg8(0xE000, 4);
memset(ExWRAM, 0x00, 32768 + 8192);
SetWriteHandler(0x6000, 0xDFFF, CartBW);
SetReadHandler(0x6000, 0xFFFF, CartBR);
} else {
memset(ExWRAM, 0x00, 8192);
SetReadHandler(0x6000, 0x7FFF, CartBR);
SetWriteHandler(0x6000, 0x7FFF, CartBW);
SetupCartPRGMapping(0, NSFDATA, ((NSFMaxBank + 1) * 4096), 0);
SetupCartPRGMapping(1, ExWRAM, 8192, 1);
setprg8r(1, 0x6000, 0);
SetReadHandler(0x8000, 0xFFFF, CartBR);
}
if (BSon) {
int32 x;
for (x = 0; x < 8; x++) {
if (NSFHeader.SoundChip & 4 && x >= 6)
BANKSET(0x6000 + (x - 6) * 4096, NSFHeader.BankSwitch[x]);
BANKSET(0x8000 + x * 4096, NSFHeader.BankSwitch[x]);
}
} else {
int32 x;
for (x = (LoadAddr & 0xF000); x < 0x10000; x += 0x1000)
BANKSET(x, ((x - (LoadAddr & 0x7000)) >> 12));
}
SetReadHandler(0xFFFA, 0xFFFD, NSFVectorRead);
SetWriteHandler(0x2000, 0x3fff, 0);
SetReadHandler(0x2000, 0x37ff, 0);
SetReadHandler(0x3836, 0x3FFF, 0);
SetReadHandler(0x3800, 0x3835, NSFROMRead);
SetWriteHandler(0x5ff6, 0x5fff, NSF_write);
SetWriteHandler(0x3ff0, 0x3fff, NSF_write);
SetReadHandler(0x3ff0, 0x3fff, NSF_read);
if (NSFHeader.SoundChip & 1) {
NSFVRC6_Init();
} else if (NSFHeader.SoundChip & 2) {
NSFVRC7_Init();
} else if (NSFHeader.SoundChip & 4) {
FDSSoundReset();
} else if (NSFHeader.SoundChip & 8) {
NSFMMC5_Init();
} else if (NSFHeader.SoundChip & 0x10) {
NSFN106_Init();
} else if (NSFHeader.SoundChip & 0x20) {
NSFAY_Init();
}
CurrentSong = NSFHeader.StartingSong;
SongReload = 0xFF;
NSFNMIFlags = 0;
}
static DECLFW(NSF_write) {
switch (A) {
case 0x3FF3: NSFNMIFlags |= 1; break;
case 0x3FF4: NSFNMIFlags &= ~2; break;
case 0x3FF5: NSFNMIFlags |= 2; break;
case 0x5FF6:
case 0x5FF7: if (!(NSFHeader.SoundChip & 4)) return;
case 0x5FF8:
case 0x5FF9:
case 0x5FFA:
case 0x5FFB:
case 0x5FFC:
case 0x5FFD:
case 0x5FFE:
case 0x5FFF: if (!BSon) return;
A &= 0xF;
BANKSET((A * 4096), V);
break;
}
}
static DECLFR(NSF_read) {
int x;
switch (A) {
case 0x3ff0: x = SongReload;
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
SongReload = 0;
return x;
case 0x3ff1:
#ifdef FCEUDEF_DEBUGGER
if (!fceuindbg)
#endif
{
memset(RAM, 0x00, 0x800);
BWrite[0x4015](0x4015, 0x0);
for (x = 0; x < 0x14; x++)
BWrite[0x4000 + x](0x4000 + x, 0);
BWrite[0x4015](0x4015, 0xF);
if (NSFHeader.SoundChip & 4) {
BWrite[0x4017](0x4017, 0xC0); /* FDS BIOS writes $C0 */
BWrite[0x4089](0x4089, 0x80);
BWrite[0x408A](0x408A, 0xE8);
} else {
memset(ExWRAM, 0x00, 8192);
BWrite[0x4017](0x4017, 0xC0);
BWrite[0x4017](0x4017, 0xC0);
BWrite[0x4017](0x4017, 0x40);
}
if (BSon) {
for (x = 0; x < 8; x++)
BANKSET(0x8000 + x * 4096, NSFHeader.BankSwitch[x]);
}
return(CurrentSong - 1);
}
case 0x3FF3: return PAL;
}
return 0;
}
uint8 FCEU_GetJoyJoy(void);
static int special = 0;
void DrawNSF(uint8 *XBuf) {
char snbuf[16];
int x;
if (vismode == 0) return;
memset(XBuf, 0, 256 * 240);
{
int32 *Bufpl;
int32 mul = 0;
int l;
l = GetSoundBuffer(&Bufpl);
if (special == 0) {
if (FSettings.SoundVolume)
mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50);
for (x = 0; x < 256; x++) {
uint32 y;
y = 142 + ((Bufpl[(x * l) >> 8] * mul) >> 14);
if (y < 240)
XBuf[x + y * 256] = 3;
}
} else if (special == 1) {
if (FSettings.SoundVolume)
mul = 8192 * 240 / (8192 * FSettings.SoundVolume / 50);
for (x = 0; x < 256; x++) {
double r;
uint32 xp, yp;
r = (Bufpl[(x * l) >> 8] * mul) >> 14;
xp = 128 + r*cos(x*M_PI*2 / 256);
yp = 120 + r*sin(x*M_PI*2 / 256);
xp &= 255;
yp %= 240;
XBuf[xp + yp * 256] = 3;
}
} else if (special == 2) {
static double theta = 0;
if (FSettings.SoundVolume)
mul = 8192 * 240 / (16384 * FSettings.SoundVolume / 50);
for (x = 0; x < 128; x++) {
double xc, yc;
double r, t;
uint32 m, n;
xc = (double)128 - x;
yc = 0 - ((double)(((Bufpl[(x * l) >> 8]) * mul) >> 14));
t = M_PI + atan(yc / xc);
r = sqrt(xc * xc + yc * yc);
t += theta;
m = 128 + r*cos(t);
n = 120 + r*sin(t);
if (m < 256 && n < 240)
XBuf[m + n * 256] = 3;
}
for (x = 128; x < 256; x++) {
double xc, yc;
double r, t;
uint32 m, n;
xc = (double)x - 128;
yc = (double)((Bufpl[(x * l) >> 8] * mul) >> 14);
t = atan(yc / xc);
r = sqrt(xc * xc + yc * yc);
t += theta;
m = 128 + r*cos(t);
n = 120 + r*sin(t);
if (m < 256 && n < 240)
XBuf[m + n * 256] = 3;
}
theta += (double)M_PI / 256;
}
}
DrawTextTrans(XBuf + 10 * 256 + 4 + (((31 - strlen((char*)NSFHeader.SongName)) << 2)), 256, NSFHeader.SongName, 6);
DrawTextTrans(XBuf + 26 * 256 + 4 + (((31 - strlen((char*)NSFHeader.Artist)) << 2)), 256, NSFHeader.Artist, 6);
DrawTextTrans(XBuf + 42 * 256 + 4 + (((31 - strlen((char*)NSFHeader.Copyright)) << 2)), 256, NSFHeader.Copyright, 6);
DrawTextTrans(XBuf + 70 * 256 + 4 + (((31 - strlen("Song:")) << 2)), 256, (uint8*)"Song:", 6);
sprintf(snbuf, "<%d/%d>", CurrentSong, NSFHeader.TotalSongs);
DrawTextTrans(XBuf + 82 * 256 + 4 + (((31 - strlen(snbuf)) << 2)), 256, (uint8*)snbuf, 6);
{
static uint8 last = 0;
uint8 tmp;
tmp = FCEU_GetJoyJoy();
if ((tmp & JOY_RIGHT) && !(last & JOY_RIGHT)) {
if (CurrentSong < NSFHeader.TotalSongs) {
CurrentSong++;
SongReload = 0xFF;
}
} else if ((tmp & JOY_LEFT) && !(last & JOY_LEFT)) {
if (CurrentSong > 1) {
CurrentSong--;
SongReload = 0xFF;
}
} else if ((tmp & JOY_UP) && !(last & JOY_UP)) {
CurrentSong += 10;
if (CurrentSong > NSFHeader.TotalSongs) CurrentSong = NSFHeader.TotalSongs;
SongReload = 0xFF;
} else if ((tmp & JOY_DOWN) && !(last & JOY_DOWN)) {
CurrentSong -= 10;
if (CurrentSong < 1) CurrentSong = 1;
SongReload = 0xFF;
} else if ((tmp & JOY_START) && !(last & JOY_START))
SongReload = 0xFF;
else if ((tmp & JOY_A) && !(last & JOY_A)) {
special = (special + 1) % 3;
}
last = tmp;
}
}
void DoNSFFrame(void) {
if (((NSFNMIFlags & 1) && SongReload) || (NSFNMIFlags & 2))
TriggerNMI();
}
void FCEUI_NSFSetVis(int mode) {
vismode = mode;
}
int FCEUI_NSFChange(int amount) {
CurrentSong += amount;
if (CurrentSong < 1) CurrentSong = 1;
else if (CurrentSong > NSFHeader.TotalSongs) CurrentSong = NSFHeader.TotalSongs;
SongReload = 0xFF;
return(CurrentSong);
}
/* Returns total songs */
int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen) {
strncpy(name, NSFHeader.SongName, maxlen);
strncpy(artist, NSFHeader.Artist, maxlen);
strncpy(copyright, NSFHeader.Copyright, maxlen);
return(NSFHeader.TotalSongs);
}

View File

@ -21,7 +21,7 @@
#include "md5.c"
//#include "movie.c"
//#include "netplay.c"
#include "drivers/libretro/fceu/nsf.c"
#include "nsf.c"
#include "palette.c"
#include "ppu.c"
#include "sound.c"