Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 82 additions & 21 deletions src/boards/mmc5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,17 +698,27 @@ void MMC5_StateRestore(int version) {
typedef struct {
uint16 wl[2];
uint8 env[2];
uint8 lengthcount[2];
uint8 decvolume[2];
uint8 deccount[2];
uint8 reloaddec;
uint8 enable;
uint8 running;
uint8 raw;
uint8 rawcontrol;
int32 fcount;
int32 dcount[2];
int32 BC[3];
int32 vcount[2];
} MMC5APU;

static MMC5APU MMC5Sound;

/* frame counter period assumed to be same as NTSC APU */
static constexpr int FHINC = 14915;

/* from sound.cpp */
extern const uint8 RectDuties[4];
extern const uint8 APULengthTable[0x20];

static void Do5PCM() {
int32 V;
Expand All @@ -732,8 +742,9 @@ static void Do5PCMHQ() {
MMC5Sound.BC[2] = SOUNDTS;
}


static DECLFW(Mapper5_SW) {
int P;

A &= 0x1F;

GameExpSound.Fill = MMC5RunSound;
Expand All @@ -745,34 +756,76 @@ static DECLFW(Mapper5_SW) {

case 0x0:
case 0x4:
if (sfun) sfun(A >> 2);
MMC5Sound.env[A >> 2] = V;
P = A >> 2;
if (sfun) sfun(P);
MMC5Sound.env[P] = V;
break;
case 0x2:
case 0x6:
if (sfun) sfun(A >> 2);
MMC5Sound.wl[A >> 2] &= ~0x00FF;
MMC5Sound.wl[A >> 2] |= V & 0xFF;
P = A >> 2;
if (sfun) sfun(P);
MMC5Sound.wl[P] &= 0xFF00;
MMC5Sound.wl[P] |= V;
break;
case 0x3:
case 0x7:
MMC5Sound.wl[A >> 2] &= ~0x0700;
MMC5Sound.wl[A >> 2] |= (V & 0x07) << 8;
MMC5Sound.running |= 1 << (A >> 2);
P = A >> 2;
if (sfun) sfun(P);
if (MMC5Sound.enable & (1 << P))
MMC5Sound.lengthcount[P] = APULengthTable[(V >> 3) & 0x1f];
MMC5Sound.wl[P] &= 0xFF;
MMC5Sound.wl[P] |= (V & 0x07) << 8;
MMC5Sound.dcount[P] = 7;
MMC5Sound.reloaddec |= 1 << P;
break;
case 0x15:
if (sfun) {
sfun(0);
sfun(1);
}
MMC5Sound.running &= V;
MMC5Sound.enable = V;
if (!(V & 1)) MMC5Sound.lengthcount[0] = 0;
if (!(V & 2)) MMC5Sound.lengthcount[1] = 0;
break;
}
}

static DECLFR(Mapper5_SR) {
return (!!MMC5Sound.lengthcount[1]) << 1 | (!!MMC5Sound.lengthcount[0]);
}

static void MMC5SoundCPUHook(int a) {
MMC5Sound.fcount -= a * 2;
if (MMC5Sound.fcount > 0) return;

MMC5Sound.fcount += FHINC;

if (sfun) {
sfun(0);
sfun(1);
}

for (int P = 0; P < 2; P++) {
bool loopmode = MMC5Sound.env[P] & 0x20;
/* length counter */
if (!loopmode && MMC5Sound.lengthcount[P])
MMC5Sound.lengthcount[P]--;
/* envelope */
if (MMC5Sound.reloaddec & (1 << P)) {
MMC5Sound.deccount[P] = MMC5Sound.env[P] & 0xF;
MMC5Sound.decvolume[P] = 0xF;
} else if (MMC5Sound.deccount[P] == 0) {
MMC5Sound.deccount[P] = MMC5Sound.env[P] & 0xF;
if (loopmode || MMC5Sound.decvolume[P])
MMC5Sound.decvolume[P] = (MMC5Sound.decvolume[P] - 1) & 0xF;
} else {
MMC5Sound.deccount[P]--;
}
}
MMC5Sound.reloaddec = 0;
}

static void Do5SQ(int P) {
static int tal[4] = { 1, 2, 4, 6 };
int32 V, amp, rthresh, wl;
int32 start, end;

Expand All @@ -782,10 +835,10 @@ static void Do5SQ(int P) {
MMC5Sound.BC[P] = end;

wl = MMC5Sound.wl[P] + 1;
amp = (MMC5Sound.env[P] & 0xF) << 4;
rthresh = tal[(MMC5Sound.env[P] & 0xC0) >> 6];
amp = (MMC5Sound.env[P] & 0x10 ? MMC5Sound.env[P] & 0xF : MMC5Sound.decvolume[P]) << 3;
rthresh = RectDuties[(MMC5Sound.env[P] & 0xC0) >> 6];

if (wl >= 8 && (MMC5Sound.running & (P + 1))) {
if (MMC5Sound.lengthcount[P]) {
int dc, vc;

wl <<= 18;
Expand All @@ -807,15 +860,14 @@ static void Do5SQ(int P) {
}

static void Do5SQHQ(int P) {
static int tal[4] = { 1, 2, 4, 6 };
uint32 V;
int32 amp, rthresh, wl;

wl = MMC5Sound.wl[P] + 1;
amp = ((MMC5Sound.env[P] & 0xF) << 8);
rthresh = tal[(MMC5Sound.env[P] & 0xC0) >> 6];
amp = (MMC5Sound.env[P] & 0x10 ? MMC5Sound.env[P] & 0xF : MMC5Sound.decvolume[P]) << 7;
rthresh = RectDuties[(MMC5Sound.env[P] & 0xC0) >> 6];

if (wl >= 8 && (MMC5Sound.running & (P + 1))) {
if (MMC5Sound.lengthcount[P]) {
int dc, vc;

wl <<= 1;
Expand Down Expand Up @@ -879,6 +931,7 @@ void Mapper5_ESI(void) {

void NSFMMC5_Init(void) {
memset(&MMC5Sound, 0, sizeof(MMC5Sound));
MMC5Sound.fcount = FHINC;
mul[0] = mul[1] = 0;
ExRAM = (uint8*)FCEU_gmalloc(1024);
Mapper5_ESI();
Expand All @@ -887,6 +940,7 @@ void NSFMMC5_Init(void) {
MMC5HackCHRMode = 2;
SetWriteHandler(0x5000, 0x5015, Mapper5_SW);
SetWriteHandler(0x5205, 0x5206, Mapper5_write);
SetReadHandler(0x5015, 0x5015, Mapper5_SR);
SetReadHandler(0x5205, 0x5206, MMC5_read);
}

Expand All @@ -900,6 +954,8 @@ void NSFMMC5_Close(void) {
}

static void GenMMC5Power(void) {
memset(&MMC5Sound, 0, sizeof(MMC5Sound));
MMC5Sound.fcount = FHINC;

PRGBanks.fill(0xFF);
WRAMPage = 0;
Expand Down Expand Up @@ -943,7 +999,7 @@ static void GenMMC5Power(void) {
SetReadHandler(0x6000, 0xFFFF, MMC5_ReadROMRAM);

SetWriteHandler(0x5000, 0x5015, Mapper5_SW);
SetWriteHandler(0x5205, 0x5206, Mapper5_write);
SetReadHandler(0x5015, 0x5015, Mapper5_SR);
SetReadHandler(0x5205, 0x5206, MMC5_read);

// GameHBIRQHook=MMC5_hb;
Expand Down Expand Up @@ -977,10 +1033,14 @@ static SFORMAT MMC5_StateRegs[] = {
{ &MMC5Sound.wl[0], 2 | FCEUSTATE_RLSB, "SDW0" },
{ &MMC5Sound.wl[1], 2 | FCEUSTATE_RLSB, "SDW1" },
{ MMC5Sound.env, 2, "SDEV" },
{ MMC5Sound.lengthcount, 2, "SDLC" },
{ MMC5Sound.decvolume, 2, "SDDV" },
{ MMC5Sound.deccount, 2, "SDDC" },
{ &MMC5Sound.reloaddec, 1, "SDRL" },
{ &MMC5Sound.enable, 1, "SDEN" },
{ &MMC5Sound.running, 1, "SDRU" },
{ &MMC5Sound.raw, 1, "SDRW" },
{ &MMC5Sound.rawcontrol, 1, "SDRC" },
{ &MMC5Sound.fcount, 4 | FCEUSTATE_RLSB, "SDFC" },

//zero 17-apr-2013 - added
{ &MMC5Sound.dcount[0], 4 | FCEUSTATE_RLSB, "DCT0" },
Expand Down Expand Up @@ -1018,6 +1078,7 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) {
BuildWRAMSizeTable();
GameStateRestore = MMC5_StateRestore;
info->Power = GenMMC5Power;
MapIRQHook = MMC5SoundCPUHook;

MMC5battery = battery;
if (battery) {
Expand Down
10 changes: 5 additions & 5 deletions src/sound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ uint8 InitialRawDALatch=0; // used only for lua
bool DMC_7bit = 0; // used to skip overclocking
ENVUNIT EnvUnits[3];

static const int RectDuties[4]={1,2,4,6};
extern const uint8 RectDuties[4]={1,2,4,6};

static int32 RectDutyCount[2];
static uint8 sweepon[2];
Expand All @@ -85,7 +85,7 @@ static int32 sqacc[2];
/* LQ variables segment ends. */

/*static*/ int32 lengthcount[4];
static const uint8 lengthtable[0x20]=
extern const uint8 APULengthTable[0x20]=
{
10,254, 20, 2, 40, 4, 80, 6, 160, 8, 60, 10, 14, 12, 26, 14,
12, 16, 24, 18, 48, 20, 96, 22, 192, 24, 72, 26, 16, 28, 32, 30
Expand Down Expand Up @@ -209,7 +209,7 @@ void LogDPCM(int romaddress, int dpcmsize){
static void SQReload(int x, uint8 V)
{
if(EnabledChannels&(1<<x))
lengthcount[x]=lengthtable[(V>>3)&0x1f];
lengthcount[x]=APULengthTable[(V>>3)&0x1f];

/* use the low 8 bits data from pulse period
* instead of from the sweep period */
Expand Down Expand Up @@ -272,7 +272,7 @@ static DECLFW(Write_PSG)
case 0xb:
DoTriangle();
if(EnabledChannels&0x4)
lengthcount[2]=lengthtable[(V>>3)&0x1f];
lengthcount[2]=APULengthTable[(V>>3)&0x1f];
TriMode=1; // Load mode
break;
case 0xC:
Expand All @@ -286,7 +286,7 @@ static DECLFW(Write_PSG)
case 0xF:
DoNoise();
if(EnabledChannels&0x8)
lengthcount[3]=lengthtable[(V>>3)&0x1f];
lengthcount[3]=APULengthTable[(V>>3)&0x1f];
EnvUnits[2].reloaddec=1;
break;
case 0x10:
Expand Down