gst/nsf/: Update our internal nosefart to nosefart-2.7-mls to fix segfaults on some files. Fixes bug #498237.

Original commit message from CVS:
Patch by: Andreas Henriksson <andreas at fatal dot set>
* gst/nsf/Makefile.am:
* gst/nsf/dis6502.h:
* gst/nsf/fds_snd.c:
* gst/nsf/fds_snd.h:
* gst/nsf/fmopl.c:
* gst/nsf/fmopl.h:
* gst/nsf/gstnsf.c:
* gst/nsf/log.c:
* gst/nsf/log.h:
* gst/nsf/memguard.c:
* gst/nsf/memguard.h:
* gst/nsf/mmc5_snd.c:
* gst/nsf/mmc5_snd.h:
* gst/nsf/nes6502.c:
* gst/nsf/nes6502.h:
* gst/nsf/nes_apu.c:
* gst/nsf/nes_apu.h:
* gst/nsf/nsf.c:
* gst/nsf/nsf.h:
* gst/nsf/osd.h:
* gst/nsf/types.h:
* gst/nsf/vrc7_snd.c:
* gst/nsf/vrc7_snd.h:
* gst/nsf/vrcvisnd.c:
* gst/nsf/vrcvisnd.h:
Update our internal nosefart to nosefart-2.7-mls to fix segfaults
on some files. Fixes bug #498237.
Remove some // comments, fix some compiler warnings and use pow()
instead of a slow, selfmade implementation.
This commit is contained in:
Andreas Henriksson 2008-03-25 15:56:13 +00:00 committed by Sebastian Dröge
parent 09ec92549f
commit a4d0dacec2
26 changed files with 1736 additions and 506 deletions

View file

@ -1,3 +1,38 @@
2008-03-25 Sebastian Dröge <slomo@circular-chaos.org>
Patch by: Andreas Henriksson <andreas at fatal dot set>
* gst/nsf/Makefile.am:
* gst/nsf/dis6502.h:
* gst/nsf/fds_snd.c:
* gst/nsf/fds_snd.h:
* gst/nsf/fmopl.c:
* gst/nsf/fmopl.h:
* gst/nsf/gstnsf.c:
* gst/nsf/log.c:
* gst/nsf/log.h:
* gst/nsf/memguard.c:
* gst/nsf/memguard.h:
* gst/nsf/mmc5_snd.c:
* gst/nsf/mmc5_snd.h:
* gst/nsf/nes6502.c:
* gst/nsf/nes6502.h:
* gst/nsf/nes_apu.c:
* gst/nsf/nes_apu.h:
* gst/nsf/nsf.c:
* gst/nsf/nsf.h:
* gst/nsf/osd.h:
* gst/nsf/types.h:
* gst/nsf/vrc7_snd.c:
* gst/nsf/vrc7_snd.h:
* gst/nsf/vrcvisnd.c:
* gst/nsf/vrcvisnd.h:
Update our internal nosefart to nosefart-2.7-mls to fix segfaults
on some files. Fixes bug #498237.
Remove some // comments, fix some compiler warnings and use pow()
instead of a slow, selfmade implementation.
2008-03-25 Sebastian Dröge <slomo@circular-chaos.org>
Patch by: Ed Catmur <ed at catmur dot co dot uk>

View file

@ -9,7 +9,8 @@ NOSEFART_SOURCES=fmopl.c \
fds_snd.c \
nes6502.c \
nsf.c \
vrcvisnd.c
vrcvisnd.c \
memguard.c
NOSEFART_INCLUDES=fmopl.h \
log.h \
@ -22,7 +23,8 @@ NOSEFART_INCLUDES=fmopl.h \
nes6502.h \
nsf.h \
types.h \
vrcvisnd.h
vrcvisnd.h \
memguard.h
libgstnsf_la_SOURCES = gstnsf.c $(NOSEFART_SOURCES)

View file

@ -40,10 +40,8 @@ extern void nes6502_disasm(uint32 PC, uint8 P, uint8 A, uint8 X, uint8 Y, uint8
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:10 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -51,7 +49,6 @@ extern void nes6502_disasm(uint32 PC, uint8 P, uint8 A, uint8 X, uint8 Y, uint8
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -70,10 +67,15 @@ extern void nes6502_disasm(uint32 PC, uint8 P, uint8 A, uint8 X, uint8 Y, uint8
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.4 2000/06/09 15:12:25 matt
** initial revision
**
*/

View file

@ -23,7 +23,6 @@
** $Id$
*/
#include <stdio.h>
#include "types.h"
#include "nes_apu.h"
#include "fds_snd.h"
@ -67,7 +66,7 @@ fds_shutdown (void)
static apu_memwrite fds_memwrite[] = {
{0x4040, 0x4092, fds_write},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
apuext_t fds_ext = {
@ -81,19 +80,8 @@ apuext_t fds_ext = {
/*
** $Log$
** Revision 1.2 2006/10/17 11:04:14 tpm
** Patch by: Josep Torra Valles <josep at fluendo com>
** * gst/nsf/fds_snd.c:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/nsf.c:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrcvisnd.c:
** Fix some things the Forte compiler warns about (#362626).
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.3 2008/03/25 15:56:10 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -101,7 +89,6 @@ apuext_t fds_ext = {
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -120,7 +107,13 @@ apuext_t fds_ext = {
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.3 2000/07/03 02:18:53 matt
** much better external module exporting

View file

@ -35,10 +35,8 @@ extern apuext_t fds_ext;
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:10 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -46,7 +44,6 @@ extern apuext_t fds_ext;
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -65,7 +62,13 @@ extern apuext_t fds_ext;
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.2 2000/06/20 04:06:16 matt
** migrated external sound definition to apu module
@ -74,4 +77,3 @@ extern apuext_t fds_ext;
** initial revision
**
*/

View file

@ -18,9 +18,9 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
/*#include "driver.h" *//* use M.A.M.E. */
#include "fmopl.h"
#include <math.h>
/* MPC - hacks */
#include "types.h"
@ -156,33 +156,16 @@ static const INT32 SL_TABLE[16] = {
#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
/* TL.TABLE[ 0 to TL_MAX ] : plus section */
/* TL.TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
static union
{
INT32 *TABLE;
void *TABLE_PTR;
} TL;
/* TL_TABLE[ 0 to TL_MAX ] : plus section */
/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
static INT32 *TL_TABLE;
/* pointers to TL.TABLE with sinwave output offset */
static union
{
INT32 **TABLE;
void *TABLE_PTR;
} SIN;
/* pointers to TL_TABLE with sinwave output offset */
static INT32 **SIN_TABLE;
/* LFO table */
static union
{
INT32 *TABLE;
void *TABLE_PTR;
} AMS;
static union
{
INT32 *TABLE;
void *TABLE_PTR;
} VIB;
static INT32 *AMS_TABLE;
static INT32 *VIB_TABLE;
/* envelope output curve table */
/* attack + decay + OFF */
@ -549,12 +532,10 @@ OPL_CALC_RH (OPL_CH * CH)
/* connectoion */
outd[0] += OP_OUT (SLOT, env_out, feedback2) * 2;
}
/* SD (17) = mul14[fnum7] + white noise
* TAM (15) = mul15[fnum8]
* TOP (18) = fnum6(mul18[fnum8]+whitenoise)
* HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
*/
TAM (15) = mul15[fnum8]
TOP (18) = fnum6(mul18[fnum8]+whitenoise)
HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise */
env_sd = OPL_CALC_SLOT (SLOT7_2) + whitenoise;
env_tam = OPL_CALC_SLOT (SLOT8_1);
env_top = OPL_CALC_SLOT (SLOT8_2);
@ -638,62 +619,62 @@ OPLOpenTable (void)
double pom;
/* allocate dynamic tables */
if ((TL.TABLE = malloc (TL_MAX * 2 * sizeof (INT32))) == NULL)
if ((TL_TABLE = malloc (TL_MAX * 2 * sizeof (INT32))) == NULL)
return 0;
if ((SIN.TABLE = malloc (SIN_ENT * 4 * sizeof (INT32 *))) == NULL) {
free (TL.TABLE_PTR);
if ((SIN_TABLE = malloc (SIN_ENT * 4 * sizeof (INT32 *))) == NULL) {
free (TL_TABLE);
return 0;
}
if ((AMS.TABLE = malloc (AMS_ENT * 2 * sizeof (INT32))) == NULL) {
free (TL.TABLE_PTR);
free (SIN.TABLE_PTR);
if ((AMS_TABLE = malloc (AMS_ENT * 2 * sizeof (INT32))) == NULL) {
free (TL_TABLE);
free (SIN_TABLE);
return 0;
}
if ((VIB.TABLE = malloc (VIB_ENT * 2 * sizeof (INT32))) == NULL) {
free (TL.TABLE_PTR);
free (SIN.TABLE_PTR);
free (AMS.TABLE_PTR);
if ((VIB_TABLE = malloc (VIB_ENT * 2 * sizeof (INT32))) == NULL) {
free (TL_TABLE);
free (SIN_TABLE);
free (AMS_TABLE);
return 0;
}
/* make total level table */
for (t = 0; t < EG_ENT - 1; t++) {
rate = ((1 << TL_BITS) - 1) / pow (10, EG_STEP * t / 20); /* dB -> voltage */
TL.TABLE[t] = (int) rate;
TL.TABLE[TL_MAX + t] = -TL.TABLE[t];
/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL.TABLE[t]));*/
TL_TABLE[t] = (int) rate;
TL_TABLE[TL_MAX + t] = -TL_TABLE[t];
/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
}
/* fill volume off area */
for (t = EG_ENT - 1; t < TL_MAX; t++) {
TL.TABLE[t] = TL.TABLE[TL_MAX + t] = 0;
TL_TABLE[t] = TL_TABLE[TL_MAX + t] = 0;
}
/* make sinwave table (total level offet) */
/* degree 0 = degree 180 = off */
SIN.TABLE[0] = SIN.TABLE[SIN_ENT / 2] = &TL.TABLE[EG_ENT - 1];
SIN_TABLE[0] = SIN_TABLE[SIN_ENT / 2] = &TL_TABLE[EG_ENT - 1];
for (s = 1; s <= SIN_ENT / 4; s++) {
pom = sin (2 * PI * s / SIN_ENT); /* sin */
pom = 20 * log10 (1 / pom); /* decibel */
j = (int) (pom / EG_STEP); /* TL.TABLE steps */
j = (int) (pom / EG_STEP); /* TL_TABLE steps */
/* degree 0 - 90 , degree 180 - 90 : plus section */
SIN.TABLE[s] = SIN.TABLE[SIN_ENT / 2 - s] = &TL.TABLE[j];
SIN_TABLE[s] = SIN_TABLE[SIN_ENT / 2 - s] = &TL_TABLE[j];
/* degree 180 - 270 , degree 360 - 270 : minus section */
SIN.TABLE[SIN_ENT / 2 + s] = SIN.TABLE[SIN_ENT - s] = &TL.TABLE[TL_MAX + j];
SIN_TABLE[SIN_ENT / 2 + s] = SIN_TABLE[SIN_ENT - s] = &TL_TABLE[TL_MAX + j];
/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
}
for (s = 0; s < SIN_ENT; s++) {
SIN.TABLE[SIN_ENT * 1 + s] =
s < (SIN_ENT / 2) ? SIN.TABLE[s] : &TL.TABLE[EG_ENT];
SIN.TABLE[SIN_ENT * 2 + s] = SIN.TABLE[s % (SIN_ENT / 2)];
SIN.TABLE[SIN_ENT * 3 + s] =
(s / (SIN_ENT / 4)) & 1 ? &TL.TABLE[EG_ENT] : SIN.TABLE[SIN_ENT * 2 +
SIN_TABLE[SIN_ENT * 1 + s] =
s < (SIN_ENT / 2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
SIN_TABLE[SIN_ENT * 2 + s] = SIN_TABLE[s % (SIN_ENT / 2)];
SIN_TABLE[SIN_ENT * 3 + s] =
(s / (SIN_ENT / 4)) & 1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT * 2 +
s];
}
/* envelope counter -> envelope output table */
for (i = 0; i < EG_ENT; i++) {
/* ATTACK curve */
pom = pow (((double) (EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
pom = (float) pow (((double) (EG_ENT - 1 - i) / EG_ENT), 8) * EG_ENT;
/* if( pom >= EG_ENT ) pom = EG_ENT-1; */
ENV_CURVE[i] = (int) pom;
/* DECAY ,RELEASE curve */
@ -704,17 +685,17 @@ OPLOpenTable (void)
/* make LFO ams table */
for (i = 0; i < AMS_ENT; i++) {
pom = (1.0 + sin (2 * PI * i / AMS_ENT)) / 2; /* sin */
AMS.TABLE[i] = (INT32) ((1.0 / EG_STEP) * pom); /* 1dB */
AMS.TABLE[AMS_ENT + i] = (INT32) ((4.8 / EG_STEP) * pom); /* 4.8dB */
AMS_TABLE[i] = (INT32) ((1.0 / EG_STEP) * pom); /* 1dB */
AMS_TABLE[AMS_ENT + i] = (INT32) ((4.8 / EG_STEP) * pom); /* 4.8dB */
}
/* make LFO vibrate table */
for (i = 0; i < VIB_ENT; i++) {
/* 100cent = 1seminote = 6% ?? */
pom = (double) VIB_RATE *0.06 * sin (2 * PI * i / VIB_ENT); /* +-100sect step */
VIB.TABLE[i] = VIB_RATE + (INT32) (pom * 0.07); /* +- 7cent */
VIB.TABLE[VIB_ENT + i] = VIB_RATE + (INT32) (pom * 0.14); /* +-14cent */
/* LOG(LOG_INF,("vib %d=%d\n",i,VIB.TABLE[VIB_ENT+i])); */
VIB_TABLE[i] = VIB_RATE + (INT32) (pom * 0.07); /* +- 7cent */
VIB_TABLE[VIB_ENT + i] = VIB_RATE + (INT32) (pom * 0.14); /* +-14cent */
/* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
}
return 1;
}
@ -723,10 +704,10 @@ OPLOpenTable (void)
static void
OPLCloseTable (void)
{
free (TL.TABLE_PTR);
free (SIN.TABLE_PTR);
free (AMS.TABLE_PTR);
free (VIB.TABLE_PTR);
free (TL_TABLE);
free (SIN_TABLE);
free (AMS_TABLE);
free (VIB_TABLE);
}
/* CSM Key Controll */
@ -794,8 +775,8 @@ OPLWriteReg (FM_OPL * OPL, int r, int v)
int c;
for (c = 0; c < OPL->max_ch; c++) {
OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN.TABLE[0];
OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN.TABLE[0];
OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
}
}
}
@ -916,8 +897,8 @@ OPLWriteReg (FM_OPL * OPL, int r, int v)
{
UINT8 rkey = OPL->rythm ^ v;
OPL->ams_table = &AMS.TABLE[v & 0x80 ? AMS_ENT : 0];
OPL->vib_table = &VIB.TABLE[v & 0x40 ? VIB_ENT : 0];
OPL->ams_table = &AMS_TABLE[v & 0x80 ? AMS_ENT : 0];
OPL->vib_table = &VIB_TABLE[v & 0x40 ? VIB_ENT : 0];
OPL->rythm = v & 0x3f;
if (OPL->rythm & 0x20) {
#if 0
@ -1022,7 +1003,7 @@ OPLWriteReg (FM_OPL * OPL, int r, int v)
CH = &OPL->P_CH[slot / 2];
if (OPL->wavesel) {
/* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
CH->SLOT[slot & 1].wavetable = &SIN.TABLE[(v & 0x03) * SIN_ENT];
CH->SLOT[slot & 1].wavetable = &SIN_TABLE[(v & 0x03) * SIN_ENT];
}
return;
}
@ -1200,7 +1181,7 @@ OPLResetChip (FM_OPL * OPL)
/* OPL->P_CH[c].PAN = OPN_CENTER; */
for (s = 0; s < 2; s++) {
/* wave table */
CH->SLOT[s].wavetable = &SIN.TABLE[0];
CH->SLOT[s].wavetable = &SIN_TABLE[0];
/* CH->SLOT[s].evm = ENV_MOD_RR; */
CH->SLOT[s].evc = EG_OFF;
CH->SLOT[s].eve = EG_OFF + 1;
@ -1270,10 +1251,8 @@ OPLCreate (int type, int clock, int rate)
void
OPLDestroy (FM_OPL * OPL)
{
void *t = OPL;
OPL_UnLockTable ();
free (t);
free (OPL);
}
/* ---------- Option handlers ---------- */

View file

@ -162,3 +162,4 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
#endif

View file

@ -108,7 +108,7 @@ static void gst_nsfdec_set_property (GObject * object, guint prop_id,
static GstElementClass *parent_class = NULL;
//static guint gst_nsfdec_signals[LAST_SIGNAL] = { 0 };
/* static guint gst_nsfdec_signals[LAST_SIGNAL] = { 0 }; */
GType
gst_nsfdec_get_type (void)

View file

@ -107,10 +107,8 @@ log_printf (const char *format, ...)
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -118,7 +116,6 @@ log_printf (const char *format, ...)
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -137,7 +134,13 @@ log_printf (const char *format, ...)
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.5 2000/06/26 04:55:33 matt
** minor change

View file

@ -37,10 +37,8 @@ extern void log_printf(const char *format, ...);
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -48,7 +46,6 @@ extern void log_printf(const char *format, ...);
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -67,10 +64,15 @@ extern void log_printf(const char *format, ...);
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.4 2000/06/09 15:12:25 matt
** initial revision
**
*/

401
gst/nsf/memguard.c Normal file
View file

@ -0,0 +1,401 @@
/*
** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
**
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of version 2 of the GNU Library General
** Public License as published by the Free Software Foundation.
**
** 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
** Library General Public License for more details. To obtain a
** copy of the GNU Library General Public License, write to the Free
** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** Any permitted reproduction of these routines, in whole or in part,
** must bear this legend.
**
**
** memguard.c
**
** memory allocation wrapper routines
**
** NOTE: based on code (c) 1998 the Retrocade group
** $Id$
*/
#include "types.h"
/* undefine macro definitions, so we get real calls */
#undef malloc
#undef free
#include <string.h>
#include <stdlib.h>
#include "memguard.h"
#include "log.h"
/* Maximum number of allocated blocks at any one time */
#define MAX_BLOCKS 16384
/* Memory block structure */
typedef struct memblock_s
{
void *block_addr;
int block_size;
char *file_name;
int line_num;
} memblock_t;
boolean mem_debug = TRUE; /* debugging flag */
#ifdef NOFRENDO_DEBUG
static int mem_blockcount = 0; /* allocated block count */
static memblock_t *mem_record = NULL;
#define GUARD_STRING "GgUuAaRrDdSsTtRrIiNnGgBbLlOoCcKk"
#define GUARD_LENGTH 64 /* before and after allocated block */
/*
** Check the memory guard to make sure out of bounds writes have not
** occurred.
*/
static boolean
mem_checkguardblock (void *data, int guard_size)
{
uint8 *orig, *chk, *blk;
int i, alloc_size;
/* get the original pointer */
orig = (((uint8 *) data) - guard_size);
/* get the size */
alloc_size = *((uint32 *) orig);
/* now skip past the size */
blk = orig + sizeof (uint32);
/* check leading guard string */
chk = GUARD_STRING;
for (i = sizeof (uint32); i < guard_size; i++) {
if (0 == *chk)
chk = GUARD_STRING;
if (*blk != *chk)
return FALSE;
chk++;
blk++;
}
/* check end of block */
chk = GUARD_STRING;
blk = ((uint8 *) data) + alloc_size;
for (i = 0; i < guard_size; i++) {
if (0 == *chk)
chk = GUARD_STRING;
if (*blk != *chk)
return FALSE;
chk++;
blk++;
}
/* we're okay! */
return TRUE;
}
/* free a guard block */
static void
mem_freeguardblock (void *data, int guard_size)
{
uint8 *orig = (((uint8 *) data) - guard_size);
free (orig);
}
/* fill in the memory guard, advance the pointer to the 'real' memory */
static void *
mem_guardblock (int alloc_size, int guard_size)
{
void *orig;
uint8 *blk, *chk;
int i;
/* allocate memory */
orig = calloc (alloc_size + (guard_size * 2), 1);
if (NULL == orig)
return NULL;
blk = ((uint8 *) orig);
/* store the size of the newly allocated block */
*((uint32 *) blk) = alloc_size;
/* skip past the size */
blk += sizeof (uint32);
/* put guard string at beginning of block */
chk = GUARD_STRING;
for (i = sizeof (uint32); i < guard_size; i++) {
if (0 == *chk)
chk = GUARD_STRING;
*blk++ = *chk++;
}
/* check end of block */
chk = GUARD_STRING;
blk = guard_size + (uint8 *) orig + alloc_size;
for (i = 0; i < guard_size; i++) {
if (0 == *chk)
chk = GUARD_STRING;
*blk++ = *chk++;
}
return (void *) (guard_size + (uint8 *) orig);
}
/* Allocate a bunch of memory to keep track of all memory blocks */
static void
mem_init (void)
{
if (mem_record) {
free (mem_record);
mem_record = NULL;
}
mem_record = calloc (MAX_BLOCKS * sizeof (memblock_t), 1);
ASSERT (mem_record);
}
/* add a block of memory to the master record */
static void
mem_addblock (void *data, int block_size, char *file, int line)
{
int i;
for (i = 0; i < MAX_BLOCKS; i++) {
if (NULL == mem_record[i].block_addr) {
mem_record[i].block_addr = data;
mem_record[i].block_size = block_size;
mem_record[i].file_name = file;
mem_record[i].line_num = line;
return;
}
}
ASSERT_MSG ("out of memory blocks.");
}
/* find an entry in the block record and delete it */
static void
mem_deleteblock (void *data, char *file, int line)
{
int i;
char fail[256];
for (i = 0; i < MAX_BLOCKS; i++) {
if (data == mem_record[i].block_addr) {
if (FALSE == mem_checkguardblock (mem_record[i].block_addr, GUARD_LENGTH)) {
sprintf (fail,
"mem_deleteblock 0x%08X at line %d of %s -- block corrupt",
(uint32) data, line, file);
ASSERT_MSG (fail);
}
memset (&mem_record[i], 0, sizeof (memblock_t));
return;
}
}
sprintf (fail, "mem_deleteblock 0x%08X at line %d of %s -- block not found",
(uint32) data, line, file);
ASSERT_MSG (fail);
}
#endif /* NOFRENDO_DEBUG */
/* allocates memory and clears it */
#ifdef NOFRENDO_DEBUG
void *
_my_malloc (int size, char *file, int line)
#else
void *
_my_malloc (int size)
#endif
{
void *temp;
char fail[256];
#ifdef NOFRENDO_DEBUG
if (NULL == mem_record && FALSE != mem_debug)
mem_init ();
if (FALSE != mem_debug)
temp = mem_guardblock (size, GUARD_LENGTH);
else
#endif /* NOFRENDO_DEBUG */
temp = calloc (sizeof (uint8), size);
if (NULL == temp) {
#ifdef NOFRENDO_DEBUG
sprintf (fail, "malloc: out of memory at line %d of %s. block size: %d\n",
line, file, size);
#else
sprintf (fail, "malloc: out of memory. block size: %d\n", size);
#endif
ASSERT_MSG (fail);
}
#ifdef NOFRENDO_DEBUG
if (FALSE != mem_debug)
mem_addblock (temp, size, file, line);
mem_blockcount++;
#endif
return temp;
}
/* free a pointer allocated with my_malloc */
#ifdef NOFRENDO_DEBUG
void
_my_free (void **data, char *file, int line)
#else
void
_my_free (void **data)
#endif
{
char fail[256];
if (NULL == data || NULL == *data
|| 0xFFFFFFFF == (uint32) * data || 0xFFFFFFFF == (uint32) data) {
#ifdef NOFRENDO_DEBUG
sprintf (fail, "free: attempted to free NULL pointer at line %d of %s\n",
line, file);
#else
sprintf (fail, "free: attempted to free NULL pointer.\n");
#endif
ASSERT_MSG (fail);
}
#ifdef NOFRENDO_DEBUG
/* if this is true, we are in REAL trouble */
if (0 == mem_blockcount) {
ASSERT_MSG ("free: attempted to free memory when no blocks available");
}
if (FALSE != mem_debug)
mem_deleteblock (*data, file, line);
mem_blockcount--; /* dec our block count */
if (FALSE != mem_debug)
mem_freeguardblock (*data, GUARD_LENGTH);
else
#endif /* NOFRENDO_DEBUG */
free (*data);
*data = NULL; /* NULL our source */
}
/* check for orphaned memory handles */
void
mem_checkleaks (void)
{
#ifdef NOFRENDO_DEBUG
int i;
if (FALSE == mem_debug)
return;
if (mem_blockcount) {
log_printf ("memory leak - %d unfreed block%s\n\n", mem_blockcount,
mem_blockcount == 1 ? "" : "s");
for (i = 0; i < MAX_BLOCKS; i++) {
if (mem_record[i].block_addr) {
log_printf ("addr: 0x%08X, size: %d, line %d of %s%s\n",
(uint32) mem_record[i].block_addr,
mem_record[i].block_size,
mem_record[i].line_num,
mem_record[i].file_name,
(FALSE == mem_checkguardblock (mem_record[i].block_addr,
GUARD_LENGTH))
? " -- block corrupt" : "");
}
}
} else
log_printf ("no memory leaks\n");
#endif
}
void
mem_checkblocks (void)
{
#ifdef NOFRENDO_DEBUG
int i;
if (FALSE == mem_debug)
return;
for (i = 0; i < MAX_BLOCKS; i++) {
if (mem_record[i].block_addr) {
if (FALSE == mem_checkguardblock (mem_record[i].block_addr, GUARD_LENGTH)) {
log_printf ("addr: 0x%08X, size: %d, line %d of %s -- block corrupt\n",
(uint32) mem_record[i].block_addr,
mem_record[i].block_size,
mem_record[i].line_num, mem_record[i].file_name);
}
}
}
#endif /* NOFRENDO_DEBUG */
}
/*
** $Log$
** Revision 1.3 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
** * gst/nsf/fds_snd.h:
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
** * gst/nsf/memguard.h:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/mmc5_snd.h:
** * gst/nsf/nes6502.c:
** * gst/nsf/nes6502.h:
** * gst/nsf/nes_apu.c:
** * gst/nsf/nes_apu.h:
** * gst/nsf/nsf.c:
** * gst/nsf/nsf.h:
** * gst/nsf/osd.h:
** * gst/nsf/types.h:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.8 2000/06/26 04:54:48 matt
** simplified and made more robust
**
** Revision 1.7 2000/06/12 01:11:41 matt
** cleaned up some error output for win32
**
** Revision 1.6 2000/06/09 15:12:25 matt
** initial revision
**
*/

98
gst/nsf/memguard.h Normal file
View file

@ -0,0 +1,98 @@
/*
** Nofrendo (c) 1998-2000 Matthew Conte (matt@conte.com)
**
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of version 2 of the GNU Library General
** Public License as published by the Free Software Foundation.
**
** 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
** Library General Public License for more details. To obtain a
** copy of the GNU Library General Public License, write to the Free
** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** Any permitted reproduction of these routines, in whole or in part,
** must bear this legend.
**
**
** memguard.h
**
** memory allocation wrapper routines
** $Id$
*/
#ifndef _MEMGUARD_H_
#define _MEMGUARD_H_
#ifdef NOFRENDO_DEBUG
#define malloc(s) _my_malloc((s), __FILE__, __LINE__)
#define free(d) _my_free((void **) &(d), __FILE__, __LINE__)
extern void *_my_malloc(int size, char *file, int line);
extern void _my_free(void **data, char *file, int line);
#else /* Non-debugging versions of calls */
#define malloc(s) _my_malloc((s))
#define free(d) _my_free((void **) &(d))
extern void *_my_malloc(int size);
extern void _my_free(void **data);
#endif /* NOFRENDO_DEBUG */
extern void mem_checkblocks(void);
extern void mem_checkleaks(void);
extern boolean mem_debug;
#endif /* _MEMGUARD_H_ */
/*
** $Log$
** Revision 1.3 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
** * gst/nsf/fds_snd.h:
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
** * gst/nsf/memguard.h:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/mmc5_snd.h:
** * gst/nsf/nes6502.c:
** * gst/nsf/nes6502.h:
** * gst/nsf/nes_apu.c:
** * gst/nsf/nes_apu.h:
** * gst/nsf/nsf.c:
** * gst/nsf/nsf.h:
** * gst/nsf/osd.h:
** * gst/nsf/types.h:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.5 2000/06/26 04:54:48 matt
** simplified and made more robust
**
** Revision 1.4 2000/06/09 15:12:25 matt
** initial revision
**
*/

View file

@ -310,13 +310,13 @@ mmc5_shutdown (void)
static apu_memread mmc5_memread[] = {
{0x5205, 0x5206, mmc5_read},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
static apu_memwrite mmc5_memwrite[] = {
{0x5000, 0x5015, mmc5_write},
{0x5205, 0x5206, mmc5_write},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
apuext_t mmc5_ext = {
@ -330,19 +330,8 @@ apuext_t mmc5_ext = {
/*
** $Log$
** Revision 1.2 2006/10/17 11:04:14 tpm
** Patch by: Josep Torra Valles <josep at fluendo com>
** * gst/nsf/fds_snd.c:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/nsf.c:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrcvisnd.c:
** Fix some things the Forte compiler warns about (#362626).
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.3 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -350,7 +339,6 @@ apuext_t mmc5_ext = {
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -369,7 +357,13 @@ apuext_t mmc5_ext = {
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.6 2000/07/04 04:51:41 matt
** cleanups

View file

@ -67,10 +67,8 @@ extern apuext_t mmc5_ext;
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -78,7 +76,6 @@ extern apuext_t mmc5_ext;
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -97,7 +94,13 @@ extern apuext_t mmc5_ext;
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.2 2000/06/20 04:06:16 matt
** migrated external sound definition to apu module
@ -106,4 +109,3 @@ extern apuext_t mmc5_ext;
** initial revision
**
*/

View file

@ -944,7 +944,7 @@
ADD_CYCLES(cycles); \
}
#define NSF_SEC() \
#define SEC() \
{ \
SET_FLAG(C_FLAG); \
ADD_CYCLES(2); \
@ -1117,9 +1117,18 @@
*/
/* register push/pull */
#ifdef NES6502_MEM_ACCESS_CTRL
# define PUSH(value) stack_push((S--),(value))
# define PULL() stack_pull((++S))
#else
# define PUSH(value) stack_page[S--] = (uint8) (value)
# define PULL() stack_page[++S]
#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */
/* Sets the Z and N flags based on given data, taken from precomputed table */
#define SET_NZ_FLAGS(value) P &= ~(N_FLAG | Z_FLAG); \
P |= flag_table[(value)]
@ -1166,82 +1175,209 @@ static uint8 *nes6502_banks[NES6502_NUMBANKS];
static uint8 *ram = NULL;
static uint8 *stack_page = NULL;
/* access flag for memory
* $$$ ben : I add this for the playing time calculation.
* Only if compiled with NES6502_MEM_ACCESS.
*/
#ifdef NES6502_MEM_ACCESS_CTRL
uint8 *acc_nes6502_banks[NES6502_NUMBANKS];
static uint8 *acc_ram = NULL;
static uint8 *acc_stack_page = NULL;
uint8 nes6502_mem_access = 0;
/* $$$ ben :
* Set memory access check flags, and store ORed frame global check
* for music time calculation.
*/
static void
chk_mem_access (uint8 * access, int flags)
{
uint8 oldchk = *access;
if ((oldchk & flags) != flags) {
nes6502_mem_access |= flags;
*access = oldchk | flags;
}
}
INLINE void
stack_push (uint8 s, uint8 v)
{
chk_mem_access (acc_stack_page + s, NES6502_WRITE_ACCESS);
stack_page[s] = v;
}
INLINE uint8
stack_pull (uint8 s)
{
chk_mem_access (acc_stack_page + s, NES6502_READ_ACCESS);
return stack_page[s];
}
INLINE uint8
zp_read (register uint32 addr)
{
chk_mem_access (acc_ram + addr, NES6502_READ_ACCESS);
return ram[addr];
}
INLINE void
zp_write (register uint32 addr, uint8 v)
{
chk_mem_access (acc_ram + addr, NES6502_WRITE_ACCESS);
ram[addr] = v;
}
#define ZP_READ(addr) zp_read((addr))
#define ZP_WRITE(addr, value) zp_write((addr),(value))
#define bank_readbyte(address) _bank_readbyte((address), NES6502_READ_ACCESS)
#define bank_readbyte_pc(address) _bank_readbyte((address), NES6502_EXE_ACCESS)
#else
# define chk_mem_access(access, flags)
/*
** Zero-page helper macros
*/
#define ZP_READ(addr) ram[(addr)]
#define ZP_WRITE(addr, value) ram[(addr)] = (uint8) (value)
#define bank_readbyte(address) _bank_readbyte((address))
#define bank_readbyte_pc(address) _bank_readbyte((address))
#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */
#ifdef NES6502_MEM_ACCESS_CTRL
int max_access[NES6502_NUMBANKS] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
INLINE uint8
bank_readbyte (register uint32 address)
_bank_readbyte (register uint32 address, const uint8 flags)
#else
INLINE uint8
_bank_readbyte (register uint32 address)
#endif
{
ASSERT (nes6502_banks[address >> NES6502_BANKSHIFT]);
#ifdef NES6502_MEM_ACCESS_CTRL
/* printf("chk_mem_access(acc_nes6502_banks[%d] + %d, %d)\n", address>>NES6502_BANKSHIFT, address & NES6502_BANKMASK, flags); */
if ((address & NES6502_BANKMASK) > max_access[address >> NES6502_BANKSHIFT]) {
max_access[address >> NES6502_BANKSHIFT] = address & NES6502_BANKMASK;
/* printf("max_access[%d] increased to %d\n", address>>NES6502_BANKSHIFT, max_access[address>>NES6502_BANKSHIFT]); */
}
#endif
chk_mem_access (acc_nes6502_banks[address >> NES6502_BANKSHIFT]
+ (address & NES6502_BANKMASK), flags);
return nes6502_banks[address >> NES6502_BANKSHIFT][address &
NES6502_BANKMASK];
}
INLINE void
bank_writebyte (register uint32 address, register uint8 value)
{
ASSERT (nes6502_banks[address >> NES6502_BANKSHIFT]);
#ifdef NES6502_MEM_ACCESS_CTRL
/* printf("chk_mem_access(acc_nes6502_banks[%d] + %d, %d)\n", address>>NES6502_BANKSHIFT, address & NES6502_BANKMASK, NES6502_WRITE_ACCESS); */
if ((address & NES6502_BANKMASK) > max_access[address >> NES6502_BANKSHIFT]) {
max_access[address >> NES6502_BANKSHIFT] = address & NES6502_BANKMASK;
/* printf("max_access[%d] increased to %d\n", address>>NES6502_BANKSHIFT, max_access[address>>NES6502_BANKSHIFT]); */
}
#endif
chk_mem_access (acc_nes6502_banks[address >> NES6502_BANKSHIFT]
+ (address & NES6502_BANKMASK), NES6502_WRITE_ACCESS);
nes6502_banks[address >> NES6502_BANKSHIFT][address & NES6502_BANKMASK] =
value;
}
/* Read a 16bit word */
#define READ_SNES_16(bank,offset) \
(\
(offset) [ (uint8 *) (bank) ] |\
((unsigned int)( ((offset)+1) [ (uint8 *) (bank) ] ) << 8)\
)
INLINE uint32
zp_address (register uint8 address)
{
#ifdef HOST_LITTLE_ENDIAN
chk_mem_access (acc_ram + address, NES6502_READ_ACCESS);
chk_mem_access (acc_ram + address + 1, NES6502_READ_ACCESS);
#if defined (HOST_LITTLE_ENDIAN) && defined(HOST_UNALIGN_WORD)
/* TODO: this fails if src address is $xFFF */
/* TODO: this fails if host architecture doesn't support byte alignment */
/* $$$ ben : DONE */
return (uint32) (*(uint16 *) (ram + address));
#else
#ifdef TARGET_CPU_PPC
#elif defined(TARGET_CPU_PPC)
return __lhbrx (ram, address);
#else
uint32 x = (uint32) * (uint16 *) (ram + address);
return (x << 8) | (x >> 8);
#endif /* TARGET_CPU_PPC */
return READ_SNES_16 (ram, address);
/* uint32 x = (uint32) *(uint16 *)(ram + address); */
/* return (x << 8) | (x >> 8); */
/* #endif *//* TARGET_CPU_PPC */
#endif /* HOST_LITTLE_ENDIAN */
}
INLINE uint32
bank_readaddress (register uint32 address)
{
#ifdef HOST_LITTLE_ENDIAN
#ifdef NES6502_MEM_ACCESS_CTRL
{
const unsigned int offset = address & NES6502_BANKMASK;
uint8 *addr = acc_nes6502_banks[address >> NES6502_BANKSHIFT];
chk_mem_access (addr + offset + 0, NES6502_READ_ACCESS);
chk_mem_access (addr + offset + 1, NES6502_READ_ACCESS);
}
#endif
#if defined (HOST_LITTLE_ENDIAN) && defined(HOST_UNALIGN_WORD)
/* TODO: this fails if src address is $xFFF */
/* TODO: this fails if host architecture doesn't support byte alignment */
/* $$$ ben : DONE */
return (uint32) (*(uint16 *) (nes6502_banks[address >> NES6502_BANKSHIFT] +
(address & NES6502_BANKMASK)));
#else
#ifdef TARGET_CPU_PPC
#elif defined(TARGET_CPU_PPC)
return __lhbrx (nes6502_banks[address >> NES6502_BANKSHIFT],
address & NES6502_BANKMASK);
#else
uint32 x =
(uint32) * (uint16 *) (nes6502_banks[address >> NES6502_BANKSHIFT] +
(address & NES6502_BANKMASK));
return (x << 8) | (x >> 8);
#endif /* TARGET_CPU_PPC */
{
const unsigned int offset = address & NES6502_BANKMASK;
return READ_SNES_16 (nes6502_banks[address >> NES6502_BANKSHIFT], offset);
}
/* uint32 x = (uint32) *(uint16 *)(nes6502_banks[address >> NES6502_BANKSHIFT] + (address & NES6502_BANKMASK)); */
/* return (x << 8) | (x >> 8); */
/* #endif *//* TARGET_CPU_PPC */
#endif /* HOST_LITTLE_ENDIAN */
}
/* read a byte of 6502 memory */
static uint8
mem_read (uint32 address)
{
/* TODO: following cases are N2A03-specific */
/* RAM */
if (address < 0x800)
if (address < 0x800) {
chk_mem_access (acc_ram + address, NES6502_READ_ACCESS);
return ram[address];
}
/* always paged memory */
/* else if (address >= 0x6000) */
else if (address >= 0x8000)
else if (address >= 0x8000) {
return bank_readbyte (address);
}
/* check memory range handlers */
else {
for (pmr = pmem_read; pmr->min_range != 0xFFFFFFFF; pmr++) {
@ -1260,6 +1396,7 @@ mem_write (uint32 address, uint8 value)
{
/* RAM */
if (address < 0x800) {
chk_mem_access (acc_ram + address, NES6502_WRITE_ACCESS);
ram[address] = value;
return;
}
@ -1286,11 +1423,19 @@ nes6502_setcontext (nes6502_context * cpu)
ASSERT (cpu);
/* Set the page pointers */
for (loop = 0; loop < NES6502_NUMBANKS; loop++)
for (loop = 0; loop < NES6502_NUMBANKS; loop++) {
nes6502_banks[loop] = cpu->mem_page[loop];
#ifdef NES6502_MEM_ACCESS_CTRL
acc_nes6502_banks[loop] = cpu->acc_mem_page[loop];
#endif
}
ram = nes6502_banks[0]; /* quicker zero-page/RAM references */
stack_page = ram + STACK_OFFSET;
#ifdef NES6502_MEM_ACCESS_CTRL
acc_ram = acc_nes6502_banks[0]; /* quicker zero-page/RAM references */
acc_stack_page = acc_ram + STACK_OFFSET;
#endif
pmem_read = cpu->read_handler;
pmem_write = cpu->write_handler;
@ -1312,8 +1457,12 @@ nes6502_getcontext (nes6502_context * cpu)
int loop;
/* Set the page pointers */
for (loop = 0; loop < NES6502_NUMBANKS; loop++)
for (loop = 0; loop < NES6502_NUMBANKS; loop++) {
cpu->mem_page[loop] = nes6502_banks[loop];
#ifdef NES6502_MEM_ACCESS_CTRL
cpu->acc_mem_page[loop] = acc_nes6502_banks[loop];
#endif
}
cpu->read_handler = pmem_read;
cpu->write_handler = pmem_write;
@ -1365,7 +1514,14 @@ nes6502_execute (int remaining_cycles)
GET_GLOBAL_REGS ();
#ifdef NES6502_MEM_ACCESS_CTRL
/* reset global memory access for this execute loop. */
nes6502_mem_access = 0;
#endif
/* Continue until we run out of cycles */
while (remaining_cycles > 0) {
instruction_cycles = 0;
@ -1398,9 +1554,10 @@ nes6502_execute (int remaining_cycles)
/* Fetch instruction */
/* nes6502_disasm(PC, P, A, X, Y, S); */
opcode = bank_readbyte (PC++);
opcode = bank_readbyte_pc (PC++);
/* Execute instruction */
switch (opcode) {
case 0x00: /* BRK */
BRK ();
@ -1641,7 +1798,7 @@ nes6502_execute (int remaining_cycles)
break;
case 0x38: /* SEC */
NSF_SEC ();
SEC ();
break;
case 0x39: /* AND $nnnn,Y */
@ -2392,25 +2549,18 @@ nes6502_setdma (int cycles)
dma_cycles += cycles;
}
#ifdef NES6502_MEM_ACCESS_CTRL
void
nes6502_chk_mem_access (uint8 * access, int flags)
{
chk_mem_access (access, flags);
}
#endif
/*
** $Log$
** Revision 1.2 2007/10/08 17:46:44 thaytan
** * gst/librfb/rfbbuffer.c: (rfb_buffer_new_and_alloc):
** * gst/librfb/rfbbuffer.h:
** * gst/librfb/rfbdecoder.c: (rfb_socket_get_buffer):
** * gst/mpegvideoparse/mpegvideoparse.c: (gst_mpegvideoparse_chain):
** * gst/nsf/nes6502.c: (nes6502_execute):
** * gst/real/gstrealaudiodec.c: (gst_real_audio_dec_setcaps):
** * gst/real/gstrealvideodec.c: (open_library):
** * gst/real/gstrealvideodec.h:
** * gst/rtpmanager/gstrtpsession.c: (create_recv_rtp_sink),
** (create_recv_rtcp_sink), (create_send_rtp_sink):
** Fix compiler warnings shown by Forte.
**
** Revision 1.1 2006-07-13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.3 2008/03/25 15:56:11 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -2418,7 +2568,6 @@ nes6502_setdma (int cycles)
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -2437,7 +2586,16 @@ nes6502_setdma (int cycles)
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.2 2003/05/01 22:34:19 benjihan
** New NSF plugin
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.6 2000/07/04 04:50:07 matt
** minor change to includes

View file

@ -23,6 +23,9 @@
** $Id$
*/
/* straitm */
#include "types.h"
/* NOTE: 16-bit addresses avoided like the plague: use 32-bit values
** wherever humanly possible
*/
@ -47,6 +50,17 @@
#define NES6502_BANKMASK ((0x10000 / NES6502_NUMBANKS) - 1)
/* Add memory access control flags. This is a ram shadow memory that holds
* for each memory bytes access flags for read, write and execute access.
* The nes6502_mem_access holds all new access (all mode all location). It is
* used to determine if the player has loop in playing time calculation.
*/
#ifdef NES6502_MEM_ACCESS_CTRL
extern uint8 nes6502_mem_access;
# define NES6502_READ_ACCESS 1
# define NES6502_WRITE_ACCESS 2
# define NES6502_EXE_ACCESS 4
#endif /* #ifdef NES6502_MEM_ACCESS_CTRL */
/* P (flag) register bitmasks */
#define N_FLAG 0x80
@ -88,6 +102,9 @@ typedef struct
typedef struct
{
uint8 * mem_page[NES6502_NUMBANKS]; /* memory page pointers */
#ifdef NES6502_MEM_ACCESS_CTRL
uint8 * acc_mem_page[NES6502_NUMBANKS]; /* memory access page pointer */
#endif
nes6502_memread *read_handler;
nes6502_memwrite *write_handler;
int dma_cycles;
@ -110,6 +127,12 @@ extern uint8 nes6502_getbyte(uint32 address);
extern uint32 nes6502_getcycles(boolean reset_flag);
extern void nes6502_setdma(int cycles);
#ifdef NES6502_MEM_ACCESS_CTRL
extern void nes6502_chk_mem_access(uint8 * access, int flags);
#else
#define nes6502_chk_mem_access(access,flags)
#endif
/* Context get/set */
extern void nes6502_setcontext(nes6502_context *cpu);
extern void nes6502_getcontext(nes6502_context *cpu);
@ -122,10 +145,8 @@ extern void nes6502_getcontext(nes6502_context *cpu);
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -133,7 +154,6 @@ extern void nes6502_getcontext(nes6502_context *cpu);
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -152,7 +172,16 @@ extern void nes6502_getcontext(nes6502_context *cpu);
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.2 2003/05/01 22:34:19 benjihan
** New NSF plugin
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.4 2000/06/09 15:12:25 matt
** initial revision

View file

@ -57,6 +57,11 @@ static int8 noise_long_lut[APU_NOISE_32K];
static int8 noise_short_lut[APU_NOISE_93];
#endif /* !REALTIME_NOISE */
/* $$$ ben : last error */
#define SET_APU_ERROR(APU,X) \
if (APU) (APU)->errstr = "apu: " X; else
#define APU_MIX_ENABLE(BIT) (apu->mix_enable&(1<<(BIT)))
/* vblank length table used for rectangles, triangle, noise */
static const uint8 vbl_length[32] = {
@ -103,15 +108,16 @@ void
apu_setcontext (apu_t * src_apu)
{
apu = src_apu;
/* $$$ ben reset eoor string here. */
SET_APU_ERROR (apu, "no error");
}
/*
** Simple queue routines
*/
#define APU_QEMPTY() (apu->q_head == apu->q_tail)
static void
static int
apu_enqueue (apudata_t * d)
{
ASSERT (apu);
@ -119,8 +125,12 @@ apu_enqueue (apudata_t * d)
apu->q_head = (apu->q_head + 1) & APUQUEUE_MASK;
if (APU_QEMPTY ())
if (APU_QEMPTY ()) {
log_printf ("apu: queue overflow\n");
SET_APU_ERROR (apu, "queue overflow");
return -1;
}
return 0;
}
static apudata_t *
@ -130,20 +140,33 @@ apu_dequeue (void)
ASSERT (apu);
if (APU_QEMPTY ())
if (APU_QEMPTY ()) {
log_printf ("apu: queue empty\n");
SET_APU_ERROR (apu, "queue empty");
/* $$$ ben : should return 0 ??? */
}
loc = apu->q_tail;
apu->q_tail = (apu->q_tail + 1) & APUQUEUE_MASK;
return &apu->queue[loc];
}
void
int
apu_setchan (int chan, boolean enabled)
{
const unsigned int max = 6;
int old;
ASSERT (apu);
apu->mix_enable[chan] = enabled;
if ((unsigned int) chan >= max) {
SET_APU_ERROR (apu, "channel out of range");
return -1;
}
old = (apu->mix_enable >> chan) & 1;
if (enabled != (boolean) - 1) {
apu->mix_enable = (apu->mix_enable & ~(1 << chan)) | ((!!enabled) << chan);
}
return old;
}
/* emulation of the 15-bit shift register the
@ -599,7 +622,7 @@ apu_regwrite (uint32 address, uint8 value)
case APU_WRB2:
chan = (address & 4) ? 1 : 0;
apu->rectangle[chan].regs[2] = value;
// if (apu->rectangle[chan].enabled)
/* if (apu->rectangle[chan].enabled) */
apu->rectangle[chan].freq =
APU_TO_FIXED ((((apu->rectangle[chan].regs[3] & 7) << 8) + value) +
1);
@ -610,7 +633,7 @@ apu_regwrite (uint32 address, uint8 value)
chan = (address & 4) ? 1 : 0;
apu->rectangle[chan].regs[3] = value;
// if (apu->rectangle[chan].enabled)
/* if (apu->rectangle[chan].enabled) */
{
apu->rectangle[chan].vbl_length = vbl_lut[value >> 3];
apu->rectangle[chan].env_vol = 0;
@ -640,7 +663,7 @@ apu_regwrite (uint32 address, uint8 value)
apu->triangle.holdnote = (value & 0x80) ? TRUE : FALSE;
// if (apu->triangle.enabled)
/* if (apu->triangle.enabled) */
{
if (FALSE == apu->triangle.counter_started && apu->triangle.vbl_length)
apu->triangle.linear_length = trilength_lut[value & 0x7F];
@ -652,7 +675,7 @@ apu_regwrite (uint32 address, uint8 value)
apu->triangle.regs[1] = value;
// if (apu->triangle.enabled)
/* if (apu->triangle.enabled) */
apu->triangle.freq =
APU_TO_FIXED ((((apu->triangle.regs[2] & 7) << 8) + value) + 1);
break;
@ -683,7 +706,7 @@ apu_regwrite (uint32 address, uint8 value)
else
apu->triangle.countmode = COUNTMODE_LOAD;
*/
// if (apu->triangle.enabled)
/* if (apu->triangle.enabled) */
{
apu->triangle.freq =
APU_TO_FIXED ((((value & 7) << 8) + apu->triangle.regs[1]) + 1);
@ -724,7 +747,7 @@ apu_regwrite (uint32 address, uint8 value)
case APU_WRD3:
apu->noise.regs[2] = value;
// if (apu->noise.enabled)
/* if (apu->noise.enabled) */
{
apu->noise.vbl_length = vbl_lut[value >> 3];
apu->noise.env_vol = 0; /* reset envelope */
@ -843,7 +866,7 @@ apu_read (uint32 address)
if (apu->noise.enabled && apu->noise.vbl_length)
value |= 0x08;
//if (apu->dmc.dma_length)
/* if (apu->dmc.dma_length) */
/* bodge for timestamp queue */
if (apu->dmc.enabled)
value |= 0x10;
@ -859,8 +882,7 @@ apu_read (uint32 address)
break;
case APU_JOY1:
value =
input_get (INP_ZAPPER | INP_JOYPAD1
value = input_get (INP_ZAPPER | INP_JOYPAD1
/*| INP_ARKANOID *//*| INP_POWERPAD */ );
break;
#endif /* !NSF_PLAYER */
@ -975,18 +997,18 @@ apu_process (void *buffer, int num_samples)
elapsed_cycles += APU_FROM_FIXED (apu->cycle_rate);
accum = 0;
if (apu->mix_enable[0])
if (APU_MIX_ENABLE (0))
accum += apu_rectangle (&apu->rectangle[0]);
if (apu->mix_enable[1])
if (APU_MIX_ENABLE (1))
accum += apu_rectangle (&apu->rectangle[1]);
if (apu->mix_enable[2])
if (APU_MIX_ENABLE (2))
accum += apu_triangle (&apu->triangle);
if (apu->mix_enable[3])
if (APU_MIX_ENABLE (3))
accum += apu_noise (&apu->noise);
if (apu->mix_enable[4])
if (APU_MIX_ENABLE (4))
accum += apu_dmc (&apu->dmc);
if (apu->ext && apu->mix_enable[5])
if (apu->ext && APU_MIX_ENABLE (5))
accum += apu->ext->process ();
/* do any filtering */
@ -1013,15 +1035,11 @@ apu_process (void *buffer, int num_samples)
/* signed 16-bit output, unsigned 8-bit */
if (16 == apu->sample_bits) {
int16 *t = buffer;
*t++ = (int16) accum;
buffer = t;
*(int16 *) (buffer) = (int16) accum;
buffer += sizeof (int16);
} else {
uint8 *t = buffer;
*t++ = (accum >> 8) ^ 0x80;
buffer = t;
*(uint8 *) (buffer) = (accum >> 8) ^ 0x80;
buffer += sizeof (uint8);
}
}
@ -1030,12 +1048,21 @@ apu_process (void *buffer, int num_samples)
}
/* set the filter type */
void
/* $$$ ben :
* Add a get feature (filter_type == -1) and returns old filter type
*/
int
apu_setfilter (int filter_type)
{
int old;
ASSERT (apu);
old = apu->filter_type;
if (filter_type != -1) {
apu->filter_type = filter_type;
}
return old;
}
void
apu_reset (void)
@ -1100,12 +1127,16 @@ apu_t *
apu_create (int sample_rate, int refresh_rate, int sample_bits, boolean stereo)
{
apu_t *temp_apu;
int channel;
/* int channel; */
temp_apu = malloc (sizeof (apu_t));
if (NULL == temp_apu)
return NULL;
/* $$$ ben : safety net, in case we forgot to init something */
memset (temp_apu, 0, sizeof (apu_t));
SET_APU_ERROR (temp_apu, "no error");
temp_apu->sample_rate = sample_rate;
temp_apu->refresh_rate = refresh_rate;
temp_apu->sample_bits = sample_bits;
@ -1124,8 +1155,9 @@ apu_create (int sample_rate, int refresh_rate, int sample_bits, boolean stereo)
apu_setactive (temp_apu);
apu_reset ();
for (channel = 0; channel < 6; channel++)
apu_setchan (channel, TRUE);
temp_apu->mix_enable = 0x3F;
/* for (channel = 0; channel < 6; channel++) */
/* apu_setchan(channel, TRUE); */
apu_setfilter (APU_FILTER_LOWPASS);
@ -1142,24 +1174,30 @@ void
apu_destroy (apu_t * src_apu)
{
if (src_apu) {
void *t = src_apu;
if (src_apu->ext)
src_apu->ext->shutdown ();
free (t);
free (src_apu);
}
}
void
int
apu_setext (apu_t * src_apu, apuext_t * ext)
{
ASSERT (src_apu);
/* $$$ ben : seem cleaner like this */
if (src_apu->ext) {
src_apu->ext->shutdown ();
}
src_apu->ext = ext;
/* initialize it */
if (src_apu->ext)
src_apu->ext->init ();
/* $$$ ben : May be one day extension int () will return error code */
return 0;
}
/* this exists for external mixing routines */
@ -1172,10 +1210,8 @@ apu_getcyclerate (void)
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -1183,7 +1219,6 @@ apu_getcyclerate (void)
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -1202,7 +1237,16 @@ apu_getcyclerate (void)
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.2 2003/04/09 14:50:32 ben
** Clean NSF api.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.19 2000/07/04 04:53:26 matt
** minor changes, sound amplification

View file

@ -249,7 +249,7 @@ typedef struct apu_s
void *buffer; /* pointer to output buffer */
int num_samples;
boolean mix_enable[6];
int mix_enable; /* $$$ben : should improve emulation */
int filter_type;
int32 cycle_rate;
@ -260,6 +260,9 @@ typedef struct apu_s
void (*process)(void *buffer, int num_samples);
/* $$$ ben : last error string */
const char * errstr;
/* external sound chip */
apuext_t *ext;
} apu_t;
@ -272,11 +275,11 @@ extern "C" {
/* Function prototypes */
extern apu_t *apu_create(int sample_rate, int refresh_rate, int sample_bits, boolean stereo);
extern void apu_destroy(apu_t *apu);
extern void apu_setext(apu_t *apu, apuext_t *ext);
extern void apu_setfilter(int filter_type);
extern int apu_setext(apu_t *apu, apuext_t *ext);
extern int apu_setfilter(int filter_type);
extern void apu_process(void *buffer, int num_samples);
extern void apu_reset(void);
extern void apu_setchan(int chan, boolean enabled);
extern int apu_setchan(int chan, boolean enabled);
extern int32 apu_getcyclerate(void);
extern apu_t *apu_getcontext(void);
@ -286,6 +289,9 @@ extern void apu_write(uint32 address, uint8 value);
/* for visualization */
extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits);
/* FIXME: added while importing for GStreamer */
void apu_setcontext(apu_t *src_apu);
#ifdef __cplusplus
}
@ -295,10 +301,8 @@ extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits);
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -306,7 +310,6 @@ extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits);
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -325,7 +328,16 @@ extern void apu_getpcmdata(void **data, int *num_samples, int *sample_bits);
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.2 2003/04/09 14:50:32 ben
** Clean NSF api.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.12 2000/07/04 04:54:48 matt
** minor changes that helped with MAME

View file

@ -23,6 +23,7 @@
** $Id$
*/
#include <stdio.h>
#include <string.h>
#include "types.h"
@ -52,12 +53,16 @@ nsf_setcontext (nsf_t * nsf)
static uint8
read_mirrored_ram (uint32 address)
{
nes6502_chk_mem_access (&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF],
NES6502_READ_ACCESS);
return cur_nsf->cpu->mem_page[0][address & 0x7FF];
}
static void
write_mirrored_ram (uint32 address, uint8 value)
{
nes6502_chk_mem_access (&cur_nsf->cpu->acc_mem_page[0][address & 0x7FF],
NES6502_WRITE_ACCESS);
cur_nsf->cpu->mem_page[0][address & 0x7FF] = value;
}
@ -66,27 +71,32 @@ static void
nsf_bankswitch (uint32 address, uint8 value)
{
int cpu_page;
int roffset;
uint8 *offset;
cpu_page = address & 0x0F;
offset = (cur_nsf->data - (cur_nsf->load_addr & 0x0FFF)) + (value << 12);
roffset = -(cur_nsf->load_addr & 0x0FFF) + ((int) value << 12);
offset = cur_nsf->data + roffset;
nes6502_getcontext (cur_nsf->cpu);
cur_nsf->cpu->mem_page[cpu_page] = offset;
#ifdef NES6502_MEM_ACCESS_CTRL
cur_nsf->cpu->acc_mem_page[cpu_page] = offset + cur_nsf->length;
#endif
nes6502_setcontext (cur_nsf->cpu);
}
static nes6502_memread default_readhandler[] = {
{0x0800, 0x1FFF, read_mirrored_ram},
{0x4000, 0x4017, apu_read},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
static nes6502_memwrite default_writehandler[] = {
{0x0800, 0x1FFF, write_mirrored_ram},
{0x4000, 0x4017, apu_write},
{0x5FF6, 0x5FFF, nsf_bankswitch},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
static uint8
@ -251,6 +261,17 @@ nsf_inittune (nsf_t * nsf)
memset (nsf->cpu->mem_page[6], 0, 0x1000);
memset (nsf->cpu->mem_page[7], 0, 0x1000);
#ifdef NES6502_MEM_ACCESS_CTRL
memset (nsf->cpu->acc_mem_page[0], 0, 0x800);
memset (nsf->cpu->acc_mem_page[6], 0, 0x1000);
memset (nsf->cpu->acc_mem_page[7], 0, 0x1000);
memset (nsf->data + nsf->length, 0, nsf->length);
#endif
nsf->cur_frame = 0;
/* nsf->last_access_frame = 0; */
nsf->cur_frame_end = !nsf->song_frames
? 0 : nsf->song_frames[nsf->current_song];
if (nsf->bankswitched) {
/* the first hack of the NSF spec! */
if (EXT_SOUND_FDS == nsf->ext_sound_type) {
@ -289,12 +310,37 @@ nsf_inittune (nsf_t * nsf)
void
nsf_frame (nsf_t * nsf)
{
/* future expansion =) */
/*nsf_setcontext(nsf); */
/* This is how Matthew Conte left it */
/* nsf_setcontext(nsf); *//* future expansion =) */
/* This was suggested by Arne Morten Kvarving, who says: */
/* Also, I fixed a bug that prevented Nosefart to play multiple tunes at
one time (actually it was just a few missing setcontext calls in the
playback routine, it had a nice TODO commented beside it. You had to set
the cpu and apu contexts not just the nsf context).
it will affect any player that tries to use nosefart to play more than one
tune at a time.
*/
nsf_setcontext (nsf);
apu_setcontext (nsf->apu);
nes6502_setcontext (nsf->cpu);
/* one frame of NES processing */
nsf_setup_routine (nsf->play_addr, 0, 0);
nes6502_execute ((int) NES_FRAME_CYCLES);
++nsf->cur_frame;
#if defined(NES6502_MEM_ACCESS_CTRL) && 0
if (nes6502_mem_access) {
uint32 sec =
(nsf->last_access_frame + nsf->playback_rate - 1) / nsf->playback_rate;
nsf->last_access_frame = nsf->cur_frame;
fprintf (stderr, "nsf : memory access [%x] at frame #%u [%u:%02u]\n",
nes6502_mem_access, nsf->last_access_frame, sec / 60, sec % 60);
}
#endif
}
/* Deallocate memory */
@ -302,26 +348,38 @@ void
nes_shutdown (nsf_t * nsf)
{
int i;
void *mem;
ASSERT (nsf);
if (nsf->cpu) {
if (nsf->cpu->mem_page[0])
free (nsf->cpu->mem_page[0]);
for (i = 5; i <= 7; i++) {
if (nsf->cpu->mem_page[i])
free (nsf->cpu->mem_page[i]);
if (nsf->cpu->mem_page[0]) {
free (nsf->cpu->mem_page[0]); /*tracks 1 and 2 of lifeforce hang here. */
}
mem = nsf->cpu;
free (mem);
for (i = 5; i <= 7; i++) {
if (nsf->cpu->mem_page[i]) {
free (nsf->cpu->mem_page[i]);
}
}
void
#ifdef NES6502_MEM_ACCESS_CTRL
if (nsf->cpu->acc_mem_page[0]) {
free (nsf->cpu->acc_mem_page[0]);
}
for (i = 5; i <= 7; i++) {
if (nsf->cpu->acc_mem_page[i]) {
free (nsf->cpu->acc_mem_page[i]);
}
}
#endif
free (nsf->cpu);
}
}
int
nsf_init (void)
{
nes6502_init ();
return 0;
}
/* Initialize NES CPU, hardware, etc. */
@ -347,19 +405,27 @@ nsf_cpuinit (nsf_t * nsf)
return -1;
}
#ifdef NES6502_MEM_ACCESS_CTRL
nsf->cpu->acc_mem_page[0] = malloc (0x800);
if (NULL == nsf->cpu->acc_mem_page[0])
return -1;
/* allocate some space for the NSF "player" MMC5 EXRAM, and WRAM */
for (i = 5; i <= 7; i++) {
nsf->cpu->acc_mem_page[i] = malloc (0x1000);
if (NULL == nsf->cpu->acc_mem_page[i])
return -1;
}
#endif
nsf->cpu->read_handler = nsf_readhandler;
nsf->cpu->write_handler = nsf_writehandler;
return 0;
}
static void
nsf_setup (nsf_t * nsf)
static unsigned int
nsf_playback_rate (nsf_t * nsf)
{
int i;
nsf->current_song = nsf->start_song;
if (nsf->pal_ntsc_bits & NSF_DEDICATED_PAL) {
if (nsf->pal_speed)
nsf->playback_rate = 1000000 / nsf->pal_speed;
@ -371,9 +437,18 @@ nsf_setup (nsf_t * nsf)
else
nsf->playback_rate = 60; /* 60 Hz */
}
return 0;
}
static void
nsf_setup (nsf_t * nsf)
{
int i;
nsf->current_song = nsf->start_song;
nsf_playback_rate (nsf);
nsf->bankswitched = FALSE;
for (i = 0; i < 8; i++) {
if (nsf->bankswitch_info[i]) {
nsf->bankswitched = TRUE;
@ -388,66 +463,296 @@ nsf_setup (nsf_t * nsf)
#define SWAP_16(x) (((uint16) x >> 8) | (((uint16) x & 0xFF) << 8))
#endif /* !HOST_LITTLE_ENDIAN */
/* Load a ROM image into memory */
nsf_t *
nsf_load (char *filename, void *source, int length)
/* $$$ ben : find extension. Should be OK with DOS, but not with some
* OS like RiscOS ... */
static char *
find_ext (char *fn)
{
FILE *fp = NULL;
char *new_fn = NULL;
nsf_t *temp_nsf;
char *a, *b, *c;
if (NULL == filename && NULL == source)
return NULL;
if (NULL == source) {
fp = fopen (filename, "rb");
/* Didn't find the file? Maybe the .NSF extension was omitted */
if (NULL == fp) {
new_fn = malloc (strlen (filename) + 5);
if (NULL == new_fn)
return NULL;
strcpy (new_fn, filename);
if (NULL == strrchr (new_fn, '.'))
strcat (new_fn, ".nsf");
fp = fopen (new_fn, "rb");
if (NULL == fp) {
void *t = new_fn;
log_printf ("could not find file '%s'\n", new_fn);
free (t);
return NULL;
}
a = strrchr (fn, '.');
b = strrchr (fn, '/');
c = strrchr (fn, '\\');
if (a <= b || a <= c) {
a = 0;
}
return a;
}
/* $$$ ben : FILE loader */
struct nsf_file_loader_t
{
struct nsf_loader_t loader;
FILE *fp;
char *fname;
int name_allocated;
};
static int
nfs_open_file (struct nsf_loader_t *loader)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
floader->name_allocated = 0;
floader->fp = 0;
if (!floader->fname) {
return -1;
}
floader->fp = fopen (floader->fname, "rb");
if (!floader->fp) {
char *fname, *ext;
ext = find_ext (floader->fname);
if (ext) {
/* There was an extension, so we do not change it */
return -1;
}
fname = malloc (strlen (floader->fname) + 5);
if (!fname) {
return -1;
}
/* try with .nsf extension. */
strcpy (fname, floader->fname);
strcat (fname, ".nsf");
floader->fp = fopen (fname, "rb");
if (!floader->fp) {
free (fname);
return -1;
}
floader->fname = fname;
floader->name_allocated = 1;
}
return 0;
}
static void
nfs_close_file (struct nsf_loader_t *loader)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
if (floader->fp) {
fclose (floader->fp);
floader->fp = 0;
}
if (floader->fname && floader->name_allocated) {
free (floader->fname);
floader->fname = 0;
floader->name_allocated = 0;
}
}
static int
nfs_read_file (struct nsf_loader_t *loader, void *data, int n)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
int r = fread (data, 1, n, floader->fp);
if (r >= 0) {
r = n - r;
}
return r;
}
static int
nfs_length_file (struct nsf_loader_t *loader)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
long save, pos;
save = ftell (floader->fp);
fseek (floader->fp, 0, SEEK_END);
pos = ftell (floader->fp);
fseek (floader->fp, save, SEEK_SET);
return pos;
}
static int
nfs_skip_file (struct nsf_loader_t *loader, int n)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
int r;
r = fseek (floader->fp, n, SEEK_CUR);
return r;
}
static const char *
nfs_fname_file (struct nsf_loader_t *loader)
{
struct nsf_file_loader_t *floader = (struct nsf_file_loader_t *) loader;
return floader->fname ? floader->fname : "<null>";
}
static struct nsf_file_loader_t nsf_file_loader = {
{
nfs_open_file,
nfs_close_file,
nfs_read_file,
nfs_length_file,
nfs_skip_file,
nfs_fname_file},
0, 0, 0
};
struct nsf_mem_loader_t
{
struct nsf_loader_t loader;
uint8 *data;
unsigned long cur;
unsigned long len;
char fname[32];
};
static int
nfs_open_mem (struct nsf_loader_t *loader)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
if (!mloader->data) {
return -1;
}
mloader->cur = 0;
sprintf (mloader->fname, "<mem(%p,%u)>",
mloader->data, (unsigned int) mloader->len);
return 0;
}
static void
nfs_close_mem (struct nsf_loader_t *loader)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
mloader->data = 0;
mloader->cur = 0;
mloader->len = 0;
}
static int
nfs_read_mem (struct nsf_loader_t *loader, void *data, int n)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
int rem;
if (n <= 0) {
return n;
}
if (!mloader->data) {
return -1;
}
rem = mloader->len - mloader->cur;
if (rem > n) {
rem = n;
}
memcpy (data, mloader->data + mloader->cur, rem);
mloader->cur += rem;
return n - rem;
}
static int
nfs_length_mem (struct nsf_loader_t *loader)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
return mloader->len;
}
static int
nfs_skip_mem (struct nsf_loader_t *loader, int n)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
unsigned long goal = mloader->cur + n;
mloader->cur = (goal > mloader->len) ? mloader->len : goal;
return goal - mloader->cur;
}
/* FIXME: not used anywhere */
#if 0
static const char *
nfs_fname_mem (struct nsf_loader_t *loader)
{
struct nsf_mem_loader_t *mloader = (struct nsf_mem_loader_t *) loader;
return mloader->fname;
}
#endif
static struct nsf_mem_loader_t nsf_mem_loader = {
{nfs_open_mem, nfs_close_mem, nfs_read_mem, nfs_length_mem, nfs_skip_mem},
0, 0, 0
};
nsf_t *
nsf_load_extended (struct nsf_loader_t *loader)
{
nsf_t *temp_nsf = 0;
int length;
char id[6];
struct
{
uint8 magic[4]; /* always "NESM" */
uint8 type[4]; /* defines extension type */
uint8 size[4]; /* extension data size (this struct include) */
} nsf_file_ext;
/* no loader ! */
if (!loader) {
return NULL;
}
/* Open the "file" */
if (loader->open (loader) < 0) {
return NULL;
}
/* Get file size, and exit if there is not enough data for NSF header
* and more since it does not make sens to have header without data.
*/
length = loader->length (loader);
/* For version 2, we do not need file length. just check error later. */
#if 0
if (length <= NSF_HEADER_SIZE) {
log_printf ("nsf : [%s] not an NSF format file\n", loader->fname (loader));
goto error;
}
#endif
/* Read magic */
if (loader->read (loader, id, 5)) {
log_printf ("nsf : [%s] error reading magic number\n",
loader->fname (loader));
goto error;
}
/* Check magic */
if (memcmp (id, NSF_MAGIC, 5)) {
log_printf ("nsf : [%s] is not an NSF format file\n",
loader->fname (loader));
goto error;
}
/* $$$ ben : Now the file should be an NSF, we can start allocating.
* first : the nsf struct
*/
temp_nsf = malloc (sizeof (nsf_t));
if (NULL == temp_nsf)
return NULL;
/* Read in the header */
if (NULL == source) {
if (fread (temp_nsf, 1, NSF_HEADER_SIZE, fp) != NSF_HEADER_SIZE) {
log_printf ("error reading file\n");
free (temp_nsf);
return NULL;
if (NULL == temp_nsf) {
log_printf ("nsf : [%s] error allocating nsf header\n",
loader->fname (loader));
goto error;
}
} else
memcpy (temp_nsf, source, NSF_HEADER_SIZE);
/* $$$ ben : safety net */
memset (temp_nsf, 0, sizeof (nsf_t));
/* Copy magic ID */
memcpy (temp_nsf, id, 5);
if (memcmp (temp_nsf->id, NSF_MAGIC, 5)) {
if (NULL == source) {
void *t = new_fn;
log_printf ("%s is not an NSF format file\n", new_fn);
fclose (fp);
free (t);
}
nsf_free (&temp_nsf);
return NULL;
/* Read header (without MAGIC) */
if (loader->read (loader, (int8 *) temp_nsf + 5, NSF_HEADER_SIZE - 5)) {
log_printf ("nsf : [%s] error reading nsf header\n",
loader->fname (loader));
goto error;
}
/* fixup endianness */
@ -458,98 +763,236 @@ nsf_load (char *filename, void *source, int length)
temp_nsf->pal_speed = SWAP_16 (temp_nsf->pal_speed);
/* we're now at position 80h */
if (NULL == source) {
fseek (fp, 0, SEEK_END);
temp_nsf->length = ftell (fp) - NSF_HEADER_SIZE;
} else {
/* Here comes the specific codes for spec version 2 */
temp_nsf->length = 0;
if (temp_nsf->version > 1) {
/* Get specified data size in reserved field (3 bytes). */
temp_nsf->length = 0 + temp_nsf->reserved[0]
+ (temp_nsf->reserved[1] << 8)
+ (temp_nsf->reserved[2] << 16);
}
/* no specified size : try to guess with file length. */
if (!temp_nsf->length) {
temp_nsf->length = length - NSF_HEADER_SIZE;
}
if (temp_nsf->length <= 0) {
log_printf ("nsf : [%s] not an NSF format file (missing data)\n",
loader->fname (loader));
goto error;
}
/* Allocate NSF space, and load it up! */
temp_nsf->data = malloc (temp_nsf->length);
{
int len = temp_nsf->length;
#ifdef NES6502_MEM_ACCESS_CTRL
/* $$$ twice memory for access control shadow mem. */
len <<= 1;
#endif
temp_nsf->data = malloc (len);
}
if (NULL == temp_nsf->data) {
log_printf ("error allocating memory for NSF data\n");
nsf_free (&temp_nsf);
return NULL;
log_printf ("nsf : [%s] error allocating nsf data\n",
loader->fname (loader));
goto error;
}
/* seek to end of header, read in data */
if (NULL == source) {
fseek (fp, NSF_HEADER_SIZE, SEEK_SET);
if (fread (temp_nsf->data, temp_nsf->length, 1, fp) != 1)
log_printf ("error reading end of header\n");
fclose (fp);
if (new_fn) {
void *t = new_fn;
free (t);
/* Read data */
if (loader->read (loader, temp_nsf->data, temp_nsf->length)) {
log_printf ("nsf : [%s] error reading NSF data\n", loader->fname (loader));
goto error;
}
} else
memcpy (temp_nsf->data, (uint8 *) source + NSF_HEADER_SIZE,
temp_nsf->length);
/* Here comes the second part of spec > 1 : get extension */
while (!loader->read (loader, &nsf_file_ext, sizeof (nsf_file_ext))
&& !memcmp (nsf_file_ext.magic, id, 4)) {
/* Got a NESM extension here. Checks for known extension type :
* right now, the only extension is "TIME" which give songs length.
* in frames.
*/
int size;
size = 0 + nsf_file_ext.size[0]
+ (nsf_file_ext.size[1] << 8)
+ (nsf_file_ext.size[2] << 16)
+ (nsf_file_ext.size[3] << 24);
if (size < sizeof (nsf_file_ext)) {
log_printf ("nsf : [%s] corrupt extension size (%d)\n",
loader->fname (loader), size);
/* Not a fatal error here. Just skip extension loading. */
break;
}
size -= sizeof (nsf_file_ext);
if (!temp_nsf->song_frames && !memcmp (nsf_file_ext.type, "TIME", 4)
&& !(size & 3)
&& (size >= 2 * 4)
&& (size <= 256 * 4)) {
uint8 tmp_time[256][4];
int tsongs = size >> 2;
int i;
int songs = temp_nsf->num_songs;
/* Add 1 for 0 which contains total time for all songs. */
++songs;
if (loader->read (loader, tmp_time, size)) {
log_printf ("nsf : [%s] missing extension data\n",
loader->fname (loader));
/* Not a fatal error here. Just skip extension loading. */
break;
}
/* Alloc song_frames for songs (not tsongs). */
temp_nsf->song_frames = malloc (sizeof (*temp_nsf->song_frames) * songs);
if (!temp_nsf->song_frames) {
log_printf ("nsf : [%s] extension alloc failed\n",
loader->fname (loader));
/* Not a fatal error here. Just skip extension loading. */
break;
}
if (tsongs > songs) {
tsongs = songs;
}
/* Copy time info. */
for (i = 0; i < tsongs; ++i) {
temp_nsf->song_frames[i] = 0 | tmp_time[i][0]
| (tmp_time[i][1] << 8)
| (tmp_time[i][2] << 16)
| (tmp_time[i][2] << 24);
}
/* Clear missing (safety net). */
for (; i < songs; ++i) {
temp_nsf->song_frames[i] = 0;
}
} else if (loader->skip (loader, size)) {
log_printf ("nsf : [%s] extension skip failed\n", loader->fname (loader));
/* Not a fatal error here. Just skip extension loading. */
break;
}
}
/* Close "file" */
loader->close (loader);
loader = 0;
/* Set up some variables */
nsf_setup (temp_nsf);
temp_nsf->apu = NULL; /* just make sure */
if (nsf_cpuinit (temp_nsf)) {
log_printf ("nsf : error cpu init\n");
goto error;
}
return temp_nsf;
/* $$$ ben : some people tell that goto are not clean. I am not agree with
* them. In most case, it allow to avoid code duplications, which are as
* most people know a source of error... Here we are sure of being clean
*/
error:
if (loader) {
loader->close (loader);
}
if (temp_nsf) {
nsf_free (&temp_nsf);
return NULL;
}
return 0;
}
return temp_nsf;
/* Load a ROM image into memory */
nsf_t *
nsf_load (const char *filename, void *source, int length)
{
struct nsf_loader_t *loader = 0;
/* $$$ ben : new loader */
if (filename) {
nsf_file_loader.fname = (char *) filename;
loader = &nsf_file_loader.loader;
} else {
nsf_mem_loader.data = source;
nsf_mem_loader.len = length;
nsf_mem_loader.fname[0] = 0;
loader = &nsf_mem_loader.loader;
}
return nsf_load_extended (loader);
}
/* Free an NSF */
void
nsf_free (nsf_t ** nsf)
nsf_free (nsf_t ** pnsf)
{
if (*nsf) {
if ((*nsf)->apu)
apu_destroy ((*nsf)->apu);
nsf_t *nsf;
nes_shutdown (*nsf);
if ((*nsf)->data) {
void *mem = (*nsf)->data;
free (mem);
if (!pnsf) {
return;
}
free (*nsf);
nsf = *pnsf;
/* $$$ ben : Don't see why passing a pointer to pointer
* is not to clear it :) */
*pnsf = 0;
if (nsf) {
if (nsf->apu)
apu_destroy (nsf->apu);
nes_shutdown (nsf);
if (nsf->data)
free (nsf->data);
if (nsf->song_frames)
free (nsf->song_frames);
free (nsf);
}
}
void
int
nsf_setchan (nsf_t * nsf, int chan, boolean enabled)
{
if (nsf) {
if (!nsf)
return -1;
nsf_setcontext (nsf);
apu_setchan (chan, enabled);
}
return apu_setchan (chan, enabled);
}
void
int
nsf_playtrack (nsf_t * nsf, int track, int sample_rate, int sample_bits,
boolean stereo)
{
ASSERT (nsf);
if (!nsf) {
return -1;
}
/* make this NSF the current context */
nsf_setcontext (nsf);
/* create the APU */
if (nsf->apu)
if (nsf->apu) {
apu_destroy (nsf->apu);
}
nsf->apu = apu_create (sample_rate, nsf->playback_rate, sample_bits, stereo);
if (NULL == nsf->apu) {
nsf_free (&nsf);
return;
/* $$$ ben : from my point of view this is not clean. Function should
* never destroy object it has not created...
*/
/* nsf_free(&nsf); */
return -1;
}
apu_setext (nsf->apu, nsf_getext (nsf));
@ -572,43 +1015,24 @@ nsf_playtrack (nsf_t * nsf, int track, int sample_rate, int sample_bits,
apu_reset ();
nsf_inittune (nsf);
return nsf->current_song;
}
void
int
nsf_setfilter (nsf_t * nsf, int filter_type)
{
if (nsf) {
nsf_setcontext (nsf);
apu_setfilter (filter_type);
if (!nsf) {
return -1;
}
nsf_setcontext (nsf);
return apu_setfilter (filter_type);
}
/*
** $Log$
** Revision 1.4 2006/10/17 11:04:14 tpm
** Patch by: Josep Torra Valles <josep at fluendo com>
** * gst/nsf/fds_snd.c:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/nsf.c:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrcvisnd.c:
** Fix some things the Forte compiler warns about (#362626).
**
** Revision 1.3 2006/07/19 11:43:50 tpm
** * gst/nsf/nsf.c: (nsf_load):
** Really fix compilation. Apparently it's not enough to
** just check the return value for errors, but we need to
** check for short reads as well (now if only we handled
** them too ...). Fixes #347935.
**
** Revision 1.2 2006/07/18 09:36:46 wtay
** * gst/nsf/nsf.c: (nsf_load):
** Fix compilation by not ignoring return values of fread.
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.5 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -616,7 +1040,6 @@ nsf_setfilter (nsf_t * nsf, int filter_type)
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -635,7 +1058,19 @@ nsf_setfilter (nsf_t * nsf, int filter_type)
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.3 2003/05/01 22:34:20 benjihan
** New NSF plugin
**
** Revision 1.2 2003/04/09 14:50:32 ben
** Clean NSF api.
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.14 2000/07/05 14:54:45 matt
** fix for naughty Crystalis rip

View file

@ -60,7 +60,8 @@ enum
{
NSF_FILTER_NONE,
NSF_FILTER_LOWPASS,
NSF_FILTER_WEIGHTED
NSF_FILTER_WEIGHTED,
NSF_FILTER_MAX, /* $$$ ben : add this one for range chacking */
};
typedef struct nsf_s
@ -90,6 +91,14 @@ typedef struct nsf_s
uint8 current_song; /* current song */
boolean bankswitched; /* is bankswitched? */
/* $$$ ben : Playing time ... */
uint32 cur_frame;
uint32 cur_frame_end;
uint32 * song_frames;
/* $$$ ben : Last error string */
const char * errstr;
/* CPU and APU contexts */
nes6502_context *cpu;
apu_t *apu;
@ -98,26 +107,49 @@ typedef struct nsf_s
void (*process)(void *buffer, int num_samples);
} nsf_t;
/* Function prototypes */
extern void nsf_init(void);
/* $$$ ben : Generic loader struct */
struct nsf_loader_t {
/* Init and open. */
int (*open)(struct nsf_loader_t * loader);
extern nsf_t *nsf_load(char *filename, void *source, int length);
/* Close and shutdown. */
void (*close) (struct nsf_loader_t * loader);
/* This function should return <0 on error, else the number of byte NOT read.
* that way a simple 0 test tell us if read was complete.
*/
int (*read) (struct nsf_loader_t * loader, void *data, int n);
/* Get file length. */
int (*length) (struct nsf_loader_t * loader);
/* Skip n bytes. */
int (*skip) (struct nsf_loader_t * loader,int n);
/* Get filename (for debug). */
const char * (*fname) (struct nsf_loader_t * loader);
};
/* Function prototypes */
extern int nsf_init(void);
extern nsf_t * nsf_load_extended(struct nsf_loader_t * loader);
extern nsf_t *nsf_load(const char *filename, void *source, int length);
extern void nsf_free(nsf_t **nsf_info);
extern void nsf_playtrack(nsf_t *nsf, int track, int sample_rate, int sample_bits,
boolean stereo);
extern int nsf_playtrack(nsf_t *nsf, int track, int sample_rate,
int sample_bits, boolean stereo);
extern void nsf_frame(nsf_t *nsf);
extern void nsf_setchan(nsf_t *nsf, int chan, boolean enabled);
extern void nsf_setfilter(nsf_t *nsf, int filter_type);
extern int nsf_setchan(nsf_t *nsf, int chan, boolean enabled);
extern int nsf_setfilter(nsf_t *nsf, int filter_type);
#endif /* _NSF_H_ */
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -125,7 +157,6 @@ extern void nsf_setfilter(nsf_t *nsf, int filter_type);
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -144,7 +175,19 @@ extern void nsf_setfilter(nsf_t *nsf, int filter_type);
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.3 2003/05/01 22:34:20 benjihan
** New NSF plugin
**
** Revision 1.2 2003/04/09 14:50:32 ben
** Clean NSF api.
**
** Revision 1.1 2003/04/08 20:53:00 ben
** Adding more files...
**
** Revision 1.11 2000/07/04 04:59:24 matt
** removed DOS-specific stuff

View file

@ -79,10 +79,8 @@ extern void osd_shutdown(void);
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -90,7 +88,6 @@ extern void osd_shutdown(void);
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -109,7 +106,13 @@ extern void osd_shutdown(void);
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.7 2000/07/04 04:45:33 matt
** moved INLINE define into types.h
@ -121,3 +124,4 @@ extern void osd_shutdown(void);
** initial revision
**
*/

View file

@ -23,16 +23,13 @@
** $Id$
*/
#ifndef _NSF_TYPES_H_
#define _NSF_TYPES_H_
#ifndef _TYPES_H_
#define _TYPES_H_
#include <glib.h> /* for types, endianness */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
/* Define this if running on little-endian (x86) systems */
#ifndef DCPLAYA
# define HOST_LITTLE_ENDIAN
#else
#undef HOST_LITTLE_ENDIAN
#endif
#ifdef __GNUC__
@ -43,15 +40,28 @@
#define INLINE static
#endif
typedef gint8 int8;
typedef gint16 int16;
typedef gint32 int32;
/* These should be changed depending on the platform */
typedef guint8 uint8;
typedef guint16 uint16;
typedef guint32 uint32;
typedef guint8 boolean;
#ifdef __BEOS__ /* added by Eli Dayan (for compiling under BeOS) */
/* use types in the BeOS Support Kit instead */
#include <be/support/SupportDefs.h>
#elif defined (DCPLAYA) /* $$$ added by ben (for compiling with dcplaya) */
# include <arch/types.h>
#else
typedef char int8;
typedef short int16;
typedef int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
#endif
typedef uint8 boolean;
#ifndef TRUE
#define TRUE 1
@ -66,6 +76,7 @@ typedef guint8 boolean;
#ifdef NOFRENDO_DEBUG
#include <stdlib.h>
#include "memguard.h"
#include "log.h"
#define ASSERT(expr) if (FALSE == (expr))\
{\
@ -79,33 +90,17 @@ typedef guint8 boolean;
exit(1);\
}
#else /* Not debugging */
#include <stdlib.h>
#include "memguard.h"
#define ASSERT(expr)
#define ASSERT_MSG(msg)
#endif
#endif /* _NSF_TYPES_H_ */
#endif /* _TYPES_H_ */
/*
** $Log$
** Revision 1.3 2007/04/17 08:48:34 tpm
** * gst/nsf/types.h:
** Rename #ifndef header guard symbol to something less generic, so
** types.h doesn't get skipped over when compiling on MingW. Include
** GLib headers and use those to set the endianness and the basic
** types so that this isn't entirely broken for non-x86 architectures.
**
** Revision 1.2 2006/07/14 09:11:11 wtay
** * gst/nsf/Makefile.am:
** * gst/nsf/memguard.c:
** * gst/nsf/memguard.h:
** * gst/nsf/types.h:
** Remove crack malloc/free replacement.
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.4 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -113,7 +108,6 @@ typedef guint8 boolean;
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -132,7 +126,13 @@ typedef guint8 boolean;
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:46:46 ben
** add new input for NES music file.
**
** Revision 1.7 2000/07/04 04:46:44 matt
** moved INLINE define from osd.h

View file

@ -138,11 +138,9 @@ vrc7_init (void)
static void
vrc7_shutdown (void)
{
void *t = buffer;
vrc7_reset ();
OPLDestroy (vrc7.ym3812);
free (t);
free (buffer);
}
/* channel (0-9), instrument (0-F), volume (0-3F, YM3812 format) */
@ -312,7 +310,7 @@ vrc7_process (void)
static apu_memwrite vrc7_memwrite[] = {
{0x9010, 0x9010, vrc7_write},
{0x9030, 0x9030, vrc7_write},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
apuext_t vrc7_ext = {
@ -326,19 +324,8 @@ apuext_t vrc7_ext = {
/*
** $Log$
** Revision 1.2 2006/10/17 11:04:14 tpm
** Patch by: Josep Torra Valles <josep at fluendo com>
** * gst/nsf/fds_snd.c:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/nsf.c:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrcvisnd.c:
** Fix some things the Forte compiler warns about (#362626).
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.3 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -346,7 +333,6 @@ apuext_t vrc7_ext = {
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -365,7 +351,13 @@ apuext_t vrc7_ext = {
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.5 2000/07/04 04:51:02 matt
** made data types stricter

View file

@ -55,10 +55,8 @@ extern apuext_t vrc7_ext;
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:12 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -66,7 +64,6 @@ extern apuext_t vrc7_ext;
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -85,7 +82,13 @@ extern apuext_t vrc7_ext;
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.3 2000/07/04 04:51:02 matt
** made data types stricter
@ -97,3 +100,4 @@ extern apuext_t vrc7_ext;
** initial revision
**
*/

View file

@ -23,7 +23,6 @@
** $Id$
*/
#include <stdio.h>
#include "types.h"
#include "vrcvisnd.h"
#include "nes_apu.h"
@ -175,7 +174,7 @@ static apu_memwrite vrcvi_memwrite[] = {
{0x9000, 0x9002, vrcvi_write}, /* vrc6 */
{0xA000, 0xA002, vrcvi_write},
{0xB000, 0xB002, vrcvi_write},
{(uint32) - 1, (uint32) - 1, NULL}
{-1, -1, NULL}
};
apuext_t vrcvi_ext = {
@ -189,19 +188,8 @@ apuext_t vrcvi_ext = {
/*
** $Log$
** Revision 1.2 2006/10/17 11:04:14 tpm
** Patch by: Josep Torra Valles <josep at fluendo com>
** * gst/nsf/fds_snd.c:
** * gst/nsf/mmc5_snd.c:
** * gst/nsf/nsf.c:
** * gst/nsf/vrc7_snd.c:
** * gst/nsf/vrcvisnd.c:
** Fix some things the Forte compiler warns about (#362626).
**
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.3 2008/03/25 15:56:13 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -209,7 +197,6 @@ apuext_t vrcvi_ext = {
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -228,7 +215,13 @@ apuext_t vrcvi_ext = {
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.9 2000/07/04 04:51:41 matt
** cleanups

View file

@ -64,10 +64,8 @@ extern apuext_t vrcvi_ext;
/*
** $Log$
** Revision 1.1 2006/07/13 15:07:28 wtay
** Based on patches by: Johan Dahlin <johan at gnome dot org>
** Ronald Bultje <rbultje at ronald dot bitfreak dot net>
** * configure.ac:
** Revision 1.2 2008/03/25 15:56:13 slomo
** Patch by: Andreas Henriksson <andreas at fatal dot set>
** * gst/nsf/Makefile.am:
** * gst/nsf/dis6502.h:
** * gst/nsf/fds_snd.c:
@ -75,7 +73,6 @@ extern apuext_t vrcvi_ext;
** * gst/nsf/fmopl.c:
** * gst/nsf/fmopl.h:
** * gst/nsf/gstnsf.c:
** * gst/nsf/gstnsf.h:
** * gst/nsf/log.c:
** * gst/nsf/log.h:
** * gst/nsf/memguard.c:
@ -94,7 +91,13 @@ extern apuext_t vrcvi_ext;
** * gst/nsf/vrc7_snd.h:
** * gst/nsf/vrcvisnd.c:
** * gst/nsf/vrcvisnd.h:
** Added NSF decoder plugin. Fixes 151192.
** Update our internal nosefart to nosefart-2.7-mls to fix segfaults
** on some files. Fixes bug #498237.
** Remove some // comments, fix some compiler warnings and use pow()
** instead of a slow, selfmade implementation.
**
** Revision 1.1 2003/04/08 20:53:01 ben
** Adding more files...
**
** Revision 1.7 2000/06/20 04:06:16 matt
** migrated external sound definition to apu module
@ -109,4 +112,3 @@ extern apuext_t vrcvi_ext;
** initial revision
**
*/