Skip to content

Commit

Permalink
-mmc5 pcm audio support
Browse files Browse the repository at this point in the history
-more title checks to see if nes game is pal
  • Loading branch information
FIX94 committed Aug 25, 2017
1 parent b033709 commit 5504dba
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 131 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ If you want to check it out for some reason I do include a windows binary in the
You will need freeglut as well as openal-soft to compile the project, it should run on most systems since it is fairly generic C code.
NTSC and PAL .nes ROMs are supported right now, it also creates .sav files if the chosen game supports saving.
Supported Mappers: 0,1,2,3,4,5,7,9,10,11,13,15,21,22,23,24,25,26,33,34,36,37,38,41,44,45,46,47,48,52,57,58,61,62,66,70,71,75,78,79,85,87,89,93,94,97,99,101,113,133,140,144,145,146,147,148,149,152,174,180,184,185,200,201,202,203,205,212,225,226,228,232,232,240 and 242.
Normal .nes files are supported, if you are starting a PAL NES title then make sure it has (E) in the name to be started in PAL mode.
Normal .nes files are supported, if you are starting a PAL NES title then make sure it has (E),(Europe),(Australia),(France),(Germany),(Italy),(Spain) or (Sweden) in the filename to be started in PAL mode.
You can also play FDS titles if you have the FDS BIOS named disksys.rom in the same folder as your .fds/.qd files.
You can also listen to .nsf files, changing tracks works by pressing left/right.
To start a file, simply drag and drop it into the fixNES Application or call it via command line with the file as argument.
Expand Down
4 changes: 2 additions & 2 deletions apu.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ bool apuCycle()
if(mmc5enabled)
{
mmc5AudioCycle();
curIn += pulseLookupTbl[mmc5Out];
curIn += pulseLookupTbl[mmc5Out]+(mmc5pcm*0.002f);
curIn *= 0.75f;
}
if(vrc7enabled)
Expand Down Expand Up @@ -459,7 +459,7 @@ bool apuCycle()
if(mmc5enabled)
{
mmc5AudioCycle();
curIn += pulseLookupTbl[mmc5Out];
curIn += pulseLookupTbl[mmc5Out]+(mmc5pcm<<6);
curIn *= 3; curIn >>= 2;
}
if(vrc7enabled)
Expand Down
128 changes: 31 additions & 97 deletions audio_mmc5.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,29 @@
//used externally
bool mmc5enabled = false;
uint8_t mmc5Out = 0;
uint8_t mmc5pcm = 0;
bool mmc5_dmcreadmode = false;

#define P1_ENABLE (1<<0)
#define P2_ENABLE (1<<1)
#define DMC_ENABLE (1<<4)

#define PULSE_CONST_V (1<<4)
#define PULSE_HALT_LOOP (1<<5)

#define DMC_HALT_LOOP (1<<6)
#define DMC_READ_MODE (1<<0)
#define DMC_IRQ_ENABLE (1<<7)

static uint8_t MMC5_IO_Reg[0x18];

static uint16_t mmc5_freq1;
static uint16_t mmc5_freq2;
/*static uint16_t mmc5_dmcFreq;
static uint16_t mmc5_dmcAddr, mmc5_dmcLen, mmc5_dmcSampleBuf;
static uint16_t mmc5_dmcCurAddr, mmc5_dmcCurLen;*/
static uint8_t mmc5_p1LengthCtr, mmc5_p2LengthCtr;
//static uint8_t mmc5_dmcVol, mmc5_dmcCurVol;
//static uint8_t dmcSampleRemain;
static uint8_t mmc5_modePos = 0;
static uint16_t mmc5_modeCurCtr = 0;
static uint16_t mmc5_p1freqCtr, mmc5_p2freqCtr;//, mmc5_dmcFreqCtr;
static uint8_t mmc5_p1Cycle, mmc5_p2Cycle;//, dmcCycle;
static bool mmc5_p1haltloop, mmc5_p2haltloop;//, mmc5_dmchaltloop;
/*static bool mmc5_dmcstart;
static bool mmc5_dmcirqenable;*/
static uint16_t mmc5_p1freqCtr, mmc5_p2freqCtr;
static uint8_t mmc5_p1Cycle, mmc5_p2Cycle;
static bool mmc5_p1haltloop, mmc5_p2haltloop;
static bool mmc5_dmcirqenable;

static envelope_t mmc5_p1Env, mmc5_p2Env;

Expand All @@ -64,20 +59,17 @@ void mmc5AudioInit()
{
memset(MMC5_IO_Reg,0,0x18);

mmc5_freq1 = 0; mmc5_freq2 = 0;// mmc5_dmcFreq = 0;
mmc5_freq1 = 0; mmc5_freq2 = 0;
mmc5_p1LengthCtr = 0; mmc5_p2LengthCtr = 0;
/*mmc5_dmcAddr = 0, mmc5_dmcLen = 0, mmc5_dmcVol = 0; mmc5_dmcSampleBuf = 0;
mmc5_dmcCurAddr = 0, mmc5_dmcCurLen = 0; mmc5_dmcCurVol = 0;
dmcSampleRemain = 0;*/
mmc5_p1freqCtr = 0; mmc5_p2freqCtr = 0;// mmc5_dmcFreqCtr = 0;
mmc5_p1Cycle = 0; mmc5_p2Cycle = 0;// dmcCycle = 0;
mmc5_p1freqCtr = 0; mmc5_p2freqCtr = 0;
mmc5_p1Cycle = 0; mmc5_p2Cycle = 0;

memset(&mmc5_p1Env,0,sizeof(envelope_t));
memset(&mmc5_p2Env,0,sizeof(envelope_t));

mmc5_p1haltloop = false; mmc5_p2haltloop = false;
/*mmc5_dmcstart = false;
mmc5_dmcirqenable = false;*/
mmc5_dmcirqenable = false;
mmc5_dmcreadmode = false;
mmc5enabled = true;
}

Expand All @@ -103,59 +95,13 @@ void mmc5AudioClockTimers()
if(mmc5_p2Cycle >= 8)
mmc5_p2Cycle = 0;
}
}

/*if(mmc5_dmcLen && (MMC5_IO_Reg[0x15] & DMC_ENABLE))
{
if(mmc5_dmcFreqCtr)
mmc5_dmcFreqCtr--;
if(mmc5_dmcFreqCtr == 0)
{
mmc5_dmcFreqCtr = mmc5_dmcFreq;
//dmcCycle++;
if(dmcSampleRemain)
{
if(mmc5_dmcSampleBuf&1)
{
if(mmc5_dmcVol <= 125)
mmc5_dmcVol += 2;
}
else if(mmc5_dmcVol >= 2)
mmc5_dmcVol -= 2;
mmc5_dmcSampleBuf>>=1;
dmcSampleRemain--;
}
if(!dmcSampleRemain)
{
if(mmc5_dmcCurLen)
{
mmc5_dmcSampleBuf = memGet8(mmc5_dmcCurAddr);
if(cpu_oam_dma > 0)
cpuIncWaitCycles(2);
else
cpuIncWaitCycles(4);
mmc5_dmcCurAddr++;
if(mmc5_dmcCurAddr < 0x8000)
mmc5_dmcCurAddr |= 0x8000;
mmc5_dmcCurLen--;
if(!mmc5_dmcCurLen)
{
if(mmc5_dmchaltloop)
{
mmc5_dmcCurAddr = mmc5_dmcAddr;
mmc5_dmcCurLen = mmc5_dmcLen;
}
else if(mmc5_dmcirqenable)
{
//printf("DMC IRQ\n");
mmc5_dmc_interrupt = true;
}
}
dmcSampleRemain = 8;
}
//dmcCycle = 0;
}
}
}*/
void mmc5AudioPCMWrite(uint8_t val)
{
if(val == 0 && mmc5_dmcirqenable)
mmc5_dmc_interrupt = true;
mmc5pcm = val;
}

static uint8_t mmc5_lastP1Out = 0, mmc5_lastP2Out = 0;
Expand Down Expand Up @@ -251,51 +197,39 @@ void mmc5AudioSet8(uint8_t reg, uint8_t val)
//printf("P2 new freq %04x\n", mmc5_freq2);
mmc5_p2Env.start = true;
}
/*else if(reg == 0x10)
else if(reg == 0x10)
{
//printf("Set 0x10 %02x\n", val);
mmc5_dmcFreq = dmcPeriod[val&0xF];
mmc5_dmchaltloop = ((val&DMC_HALT_LOOP) != 0);
mmc5_dmcirqenable = ((val&DMC_IRQ_ENABLE) != 0);
//printf("%d\n", mmc5_dmcirqenable);
mmc5_dmcreadmode = (val&DMC_READ_MODE)!=0;
mmc5_dmcirqenable = (val&DMC_IRQ_ENABLE)!=0;
if(!mmc5_dmcirqenable)
mmc5_dmc_interrupt = false;
}
else if(reg == 0x11)
mmc5_dmcVol = val&0x7F;
else if(reg == 0x12)
mmc5_dmcAddr = 0xC000+(val*64);
else if(reg == 0x13)
{
//printf("Set 0x13 %02x\n", val);
mmc5_dmcLen = (val*16)+1;
}*/
if(!mmc5_dmcreadmode)
mmc5AudioPCMWrite(val);
}
else if(reg == 0x15)
{
//printf("Set 0x15 %02x\n",val);
if(!(val & P1_ENABLE))
mmc5_p1LengthCtr = 0;
if(!(val & P2_ENABLE))
mmc5_p2LengthCtr = 0;
/*if(!(val & DMC_ENABLE))
mmc5_dmcCurLen = 0;
else if(mmc5_dmcCurLen == 0)
{
mmc5_dmcCurAddr = mmc5_dmcAddr;
mmc5_dmcCurLen = mmc5_dmcLen;
}
mmc5_dmc_interrupt = false;*/
}
}

uint8_t mmc5AudioGet8(uint8_t reg)
{
//printf("%08x\n", reg);
if(reg == 0x15)
if(reg == 0x10)
{
uint8_t intrflags = ((mmc5_dmc_interrupt<<7));
//printf("Get 0x15 %02x\n",intrflags);
return ((mmc5_p1LengthCtr > 0) | ((mmc5_p2LengthCtr > 0)<<1) | intrflags);
uint8_t intrflag = (mmc5_dmc_interrupt<<7);
//printf("Get 0x10 %02x\n",intrflag);
mmc5_dmc_interrupt = false;
return intrflag;
}
else if(reg == 0x15)
return (mmc5_p1LengthCtr > 0) | ((mmc5_p2LengthCtr > 0)<<1);
return MMC5_IO_Reg[reg];
}
3 changes: 3 additions & 0 deletions audio_mmc5.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@ void mmc5AudioClockTimers();
void mmc5AudioSet8(uint8_t reg, uint8_t val);
uint8_t mmc5AudioGet8(uint8_t reg);
void mmc5AudioLenCycle();
void mmc5AudioPCMWrite(uint8_t val);

extern bool mmc5enabled;
extern uint8_t mmc5Out;
extern uint8_t mmc5pcm;
extern bool mmc5_dmcreadmode;

#endif
6 changes: 4 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#define DEBUG_KEY 0
#define DEBUG_LOAD_INFO 1

static const char *VERSION_STRING = "fixNES Alpha v0.9.5";
static const char *VERSION_STRING = "fixNES Alpha v0.9.6";
static char window_title[256];
static char window_title_pause[256];

Expand Down Expand Up @@ -138,7 +138,9 @@ int main(int argc, char** argv)
return EXIT_SUCCESS;
}
nesEmuFileClose();
nesPAL = (strstr(emuFileName,"(E)") != NULL);
nesPAL = (strstr(emuFileName,"(E)") != NULL) || (strstr(emuFileName,"(Europe)") != NULL) || (strstr(emuFileName,"(Australia)") != NULL)
|| (strstr(emuFileName,"(France)") != NULL) || (strstr(emuFileName,"(Germany)") != NULL) || (strstr(emuFileName,"(Italy)") != NULL)
|| (strstr(emuFileName,"(Spain)") != NULL) || (strstr(emuFileName,"(Sweden)") != NULL);
uint8_t mapper = ((emuNesROM[6] & 0xF0) >> 4) | ((emuNesROM[7] & 0xF0));
emuSaveEnabled = (emuNesROM[6] & (1<<1)) != 0;
bool trainer = (emuNesROM[6] & (1<<2)) != 0;
Expand Down
38 changes: 22 additions & 16 deletions mapper/m5.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,61 +143,67 @@ uint8_t m5get8(uint16_t addr, uint8_t val)
switch(m5_prg_bank_mode)
{
case 0:
return m5_prgROM[(((m5_PRGBank[3]&~3)<<13)+(addr&0x7FFF))&m5_prgROMand];
val = m5_prgROM[(((m5_PRGBank[3]&~3)<<13)+(addr&0x7FFF))&m5_prgROMand];
break;
case 1:
if(addr < 0xC000)
{
if(m5_PRGBankType[1] == 1) //ROM
return m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
val = m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
val = m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
}
else
return m5_prgROM[(((m5_PRGBank[3]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
val = m5_prgROM[(((m5_PRGBank[3]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
break;
case 2:
if(addr < 0xC000)
{
if(m5_PRGBankType[1] == 1) //ROM
return m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
val = m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
val = m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
}
else if(addr < 0xE000)
{
if(m5_PRGBankType[2] == 1) //ROM
return m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]];
val = m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]];
}
else
return m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand];
break;
case 3:
if(addr < 0xA000)
{
if(m5_PRGBankType[0] == 1) //ROM
return m5_prgROM[((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[(((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[0]];
val = m5_prgRAM[(((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[0]];
}
else if(addr < 0xC000)
{
if(m5_PRGBankType[1] == 1) //ROM
return m5_prgROM[((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[(((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
val = m5_prgRAM[(((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[1]];
}
else if(addr < 0xE000)
{
if(m5_PRGBankType[2] == 1) //ROM
return m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand];
else //RAM
return m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]];
val = m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]];
}
else
return m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand];
val = m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand];
break;
default:
break;
}
if(addr < 0xC000 && mmc5_dmcreadmode)
mmc5AudioPCMWrite(val);
}
return val;
}
Expand Down
30 changes: 17 additions & 13 deletions mapper/nsf.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,26 +204,30 @@ uint8_t nsfget8(uint16_t addr, uint8_t val)
nsf_playing = false;
return 0x45; //high addr, 0x456A
}
return val;
}
else
{
if(addr < 0x8000 && (!fdsEnabled || !nsf_bankEnable))
return nsf_prgRAM[addr&0x1FFF];
uint32_t romAddr = nsfgetromAddr(addr);
if(romAddr >= nsf_loadAddr && (romAddr-nsf_loadAddr) < nsf_prgROMsize)
val = nsf_prgRAM[addr&0x1FFF];
else
{
uint8_t ret = nsf_prgROM[romAddr-nsf_loadAddr];
//printf("Ret from ROM %04x with %02x\n", romAddr-nsf_loadAddr, ret);
if(addr < 0xE000 && fdsEnabled)
nsf_FillRAM[addr-0x6000] = ret;
return ret;
uint32_t romAddr = nsfgetromAddr(addr);
if(romAddr >= nsf_loadAddr && (romAddr-nsf_loadAddr) < nsf_prgROMsize)
{
val = nsf_prgROM[romAddr-nsf_loadAddr];
//printf("Ret from ROM %04x with %02x\n", romAddr-nsf_loadAddr, val);
if(addr < 0xE000 && fdsEnabled)
nsf_FillRAM[addr-0x6000] = val;
}
else if(addr < 0xE000 && fdsEnabled)
val = nsf_FillRAM[addr-0x6000];
else //ROM data not available so return 0
val = 0;
if(mmc5enabled && addr >= 0x8000 && addr < 0xC000 && mmc5_dmcreadmode)
mmc5AudioPCMWrite(val);
}
else if(addr < 0xE000 && fdsEnabled)
return nsf_FillRAM[addr-0x6000];
else
return 0;
}
return val;
}

void nsfset8(uint16_t addr, uint8_t val)
Expand Down

0 comments on commit 5504dba

Please sign in to comment.