Initial integration of updated fixNES

This commit is contained in:
Jack Andersen 2018-06-16 10:09:12 -10:00
parent 079c343557
commit 56b1e562ce
8 changed files with 335 additions and 240 deletions

2
.gitmodules vendored
View File

@ -36,7 +36,7 @@
url = https://github.com/Tencent/rapidjson.git url = https://github.com/Tencent/rapidjson.git
[submodule "NESEmulator/fixNES"] [submodule "NESEmulator/fixNES"]
path = NESEmulator/fixNES path = NESEmulator/fixNES
url = https://github.com/jackoalan/fixNES.git url = https://github.com/FIX94/fixNES.git
[submodule "Editor/locale"] [submodule "Editor/locale"]
path = Editor/locale path = Editor/locale
url = ../urde-translations.git url = ../urde-translations.git

View File

@ -110,10 +110,10 @@ static const uint32_t visibleImg = VISIBLE_DOTS*VISIBLE_LINES*4;
//static uint8_t scaleFactor = 2; //static uint8_t scaleFactor = 2;
static bool emuSaveEnabled = false; static bool emuSaveEnabled = false;
static bool emuFdsHasSideB = false; static bool emuFdsHasSideB = false;
static uint32_t mainLoopRuns;
static uint32_t mainLoopPos; //static uint16_t ppuCycleTimer;
static uint16_t ppuCycleTimer; uint32_t cpuCycleTimer;
static uint16_t cpuCycleTimer; uint32_t vrc7CycleTimer;
//from input.c //from input.c
extern uint8_t inValReads[8]; extern uint8_t inValReads[8];
//from mapper.c //from mapper.c
@ -122,16 +122,13 @@ extern bool mapperUse78A;
extern bool m32_singlescreen; extern bool m32_singlescreen;
static volatile bool emuRenderFrame = false; static volatile bool emuRenderFrame = false;
extern uint8_t audioExpansion;
//used externally //used externally
bool emuSkipVsync = false; bool emuSkipVsync = false;
bool emuSkipFrame = false; bool emuSkipFrame = false;
//static uint32_t mCycles = 0; //static uint32_t mCycles = 0;
static uint16_t mainClock = 1;
static uint16_t apuClock = 1;
static uint16_t ppuClock = 1;
static uint16_t vrc7Clock = 1;
extern bool fdsSwitch; extern bool fdsSwitch;
@ -185,10 +182,6 @@ void CNESEmulator::InitializeEmulator()
{ {
nesPause = false; nesPause = false;
ppuDebugPauseFrame = false; ppuDebugPauseFrame = false;
mainClock = 1;
apuClock = 1;
ppuClock = 1;
vrc7Clock = 1;
puts(VERSION_STRING); puts(VERSION_STRING);
strcpy(window_title, VERSION_STRING); strcpy(window_title, VERSION_STRING);
@ -238,19 +231,20 @@ void CNESEmulator::InitializeEmulator()
#endif #endif
sprintf(window_title, "%s NES - %s\n", nesPAL ? "PAL" : "NTSC", VERSION_STRING); sprintf(window_title, "%s NES - %s\n", nesPAL ? "PAL" : "NTSC", VERSION_STRING);
sprintf(window_title_pause, "%s (Pause)", window_title);
sprintf(window_title_pause, "%s (Pause)", window_title); sprintf(window_title_pause, "%s (Pause)", window_title);
#if DEBUG_HZ #if DEBUG_HZ
emuFrameStart = GetTickCount(); emuFrameStart = GetTickCount();
#endif #endif
#if DEBUG_MAIN_CALLS #if DEBUG_MAIN_CALLS
emuMainFrameStart = GetTickCount(); emuMainFrameStart = GetTickCount();
#endif #endif
cpuCycleTimer = nesPAL ? 16 : 12; cpuCycleTimer = nesPAL ? 16 : 12;
//do full frame per update loop vrc7CycleTimer = 432 / cpuCycleTimer;
ppuCycleTimer = nesPAL ? 5 : 4; //do one scanline per idle loop
mainLoopRuns = nesPAL ? DOTS*ppuCycleTimer : DOTS*ppuCycleTimer; //ppuCycleTimer = nesPAL ? 5 : 4;
//mainLoopRuns *= ppuLinesTotal; //mainLoopRuns = nesPAL ? DOTS*ppuCycleTimer : DOTS*ppuCycleTimer;
mainLoopPos = mainLoopRuns; //mainLoopPos = mainLoopRuns;
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx) CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
{ {
@ -292,7 +286,7 @@ void CNESEmulator::DeinitializeEmulator()
apuDeinitBufs(); apuDeinitBufs();
if(emuNesROM != NULL) if(emuNesROM != NULL)
{ {
if(!nesEmuNSFPlayback && fdsEnabled) if(!nesEmuNSFPlayback && (audioExpansion&EXP_FDS))
{ {
FILE *save = fopen(emuSaveName, "wb"); FILE *save = fopen(emuSaveName, "wb");
if(save) if(save)
@ -392,7 +386,7 @@ size_t CNESEmulator::supplyAudio(boo::IAudioVoice& voice, size_t frames, int16_t
return frames; return frames;
} }
#define CATCHUP_SKIP 1 #define CATCHUP_SKIP 0
#if CATCHUP_SKIP #if CATCHUP_SKIP
static int catchupFrames = 0; static int catchupFrames = 0;
#endif #endif
@ -419,97 +413,53 @@ void CNESEmulator::NesEmuMainLoop(bool forceDraw)
break; break;
} }
++loopCount; ++loopCount;
if(mainClock == cpuCycleTimer)
{
//URDE uses this loop to pre-fill audio buffers,
//rather than executing multiple frame loops
bool breakout = false;
do
{
//runs every 8th cpu clock
if(apuClock == 8)
{
if(!apuCycleURDE() && !forceDraw)
{
#if DEBUG_MAIN_CALLS
emuMainTimesSkipped++;
#endif
#if CATCHUP_SKIP
catchupFrames = 0;
#endif
//printf("LC SKIP\n");
breakout = true;
break;
}
apuClock = 1;
}
else
apuClock++;
//runs every cpu cycle
apuClockTimers();
} while (emuSkipVsync);
if (breakout)
break;
//main CPU clock //main CPU clock
if(!cpuCycle()) if(!cpuCycle())
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
//mapper related irqs //run graphics
if(mapperCycle != NULL) ppuCycle();
mapperCycle(); //run audio
//mCycles++; apuCycle();
//channel timer updates //mapper related irqs
apuLenCycle(); mapperCycle();
mainClock = 1; //mCycles++;
} if(ppuDrawDone())
else
mainClock++;
if(ppuClock == ppuCycleTimer)
{ {
if(!ppuCycle()) //printf("%i\n",mCycles);
exit(EXIT_SUCCESS); //mCycles = 0;
if(ppuDrawDone()) #ifndef __LIBRETRO__
{ emuRenderFrame = true;
//printf("%i\n",mCycles); #if 0
//mCycles = 0; if(fm2playRunning())
emuRenderFrame = true; fm2playUpdate();
if(fm2playRunning())
fm2playUpdate();
#if DEBUG_HZ
emuTimesCalled++;
int end = GetTickCount();
emuTotalElapsed += end - emuFrameStart;
if(emuTotalElapsed >= 1000)
{
printf("\r%iHz ", emuTimesCalled);
emuTimesCalled = 0;
emuTotalElapsed = 0;
}
emuFrameStart = end;
#endif #endif
if(ppuDebugPauseFrame) #if (WINDOWS_BUILD && DEBUG_HZ)
{ emuTimesCalled++;
ppuDebugPauseFrame = false; DWORD end = GetTickCount();
nesPause = true; emuTotalElapsed += end - emuFrameStart;
} if(emuTotalElapsed >= 1000)
if(nesEmuNSFPlayback)
nsfVsync();
}
ppuClock = 1;
}
else
ppuClock++;
if(fdsEnabled)
fdsAudioMasterUpdate();
if(vrc7enabled)
{
if(vrc7Clock == 432)
{ {
vrc7AudioCycle(); printf("\r%iHz ", emuTimesCalled);
vrc7Clock = 1; emuTimesCalled = 0;
emuTotalElapsed = 0;
} }
else emuFrameStart = end;
vrc7Clock++; #endif
//update audio before drawing
while(!apuUpdate()) {}
//glutPostRedisplay();
#if 0
if(ppuDebugPauseFrame)
{
ppuDebugPauseFrame = false;
nesPause = true;
}
#endif
#endif
if(nesEmuNSFPlayback)
nsfVsync();
continue;
} }
#if 1 #if 1

View File

@ -17,7 +17,7 @@
bool apuCycleURDE() bool apuCycleURDE()
{ {
if(curBufPos == apuBufSize) if(apu.curBufPos == apu.BufSize)
{ {
int updateRes = audioUpdate(); int updateRes = audioUpdate();
if(updateRes == 0) if(updateRes == 0)
@ -39,134 +39,277 @@ bool apuCycleURDE()
else else
emuSkipVsync = false; emuSkipVsync = false;
} }
curBufPos = 0; apu.curBufPos = 0;
} }
uint8_t p1Out = lastP1Out, p2Out = lastP2Out,
triOut = lastTriOut, noiseOut = lastNoiseOut; uint8_t aExp = audioExpansion;
if(p1LengthCtr && (APU_IO_Reg[0x15] & P1_ENABLE)) if(!(apu.apuClock&7))
{ {
if(p1seq[p1Cycle] && !p1Sweep.mute && freq1 >= 8 && freq1 < 0x7FF) if(apu.p1LengthCtr && (apu.reg[0x15] & P1_ENABLE))
lastP1Out = p1Out = (p1Env.constant ? p1Env.vol : p1Env.decay); {
else if(!apu.p1Sweep.mute && apu.freq1 >= 8 && apu.freq1 < 0x7FF)
p1Out = 0; apu.p1Out = apu.p1seq[apu.p1Cycle] ? (apu.p1Env.constant ? apu.p1Env.vol : apu.p1Env.decay) : 0;
} }
if(p2LengthCtr && (APU_IO_Reg[0x15] & P2_ENABLE)) if(apu.p2LengthCtr && (apu.reg[0x15] & P2_ENABLE))
{ {
if(p2seq[p2Cycle] && !p2Sweep.mute && freq2 >= 8 && freq2 < 0x7FF) if(!apu.p2Sweep.mute && apu.freq2 >= 8 && apu.freq2 < 0x7FF)
lastP2Out = p2Out = (p2Env.constant ? p2Env.vol : p2Env.decay); apu.p2Out = apu.p2seq[apu.p2Cycle] ? (apu.p2Env.constant ? apu.p2Env.vol : apu.p2Env.decay) : 0;
else }
p2Out = 0; if(apu.triLengthCtr && apu.triCurLinearCtr && (apu.reg[0x15] & TRI_ENABLE))
} {
if(triLengthCtr && triCurLinearCtr && (APU_IO_Reg[0x15] & TRI_ENABLE)) if(apu.triFreq >= 2)
{ apu.triOut = apu.triSeq[apu.triCycle];
if(triSeq[triCycle] && triFreq >= 2) }
lastTriOut = triOut = triSeq[triCycle]; if(apu.noiseLengthCtr && (apu.reg[0x15] & NOISE_ENABLE))
else {
triOut = 0; if(apu.noiseFreq > 0)
} apu.noiseOut = (apu.noiseShiftReg&1) == 0 ? (apu.noiseEnv.constant ? apu.noiseEnv.vol : apu.noiseEnv.decay) : 0;
if(noiseLengthCtr && (APU_IO_Reg[0x15] & NOISE_ENABLE)) }
{
if((noiseShiftReg&1) == 0 && noiseFreq > 0)
lastNoiseOut = noiseOut = (noiseEnv.constant ? noiseEnv.vol : noiseEnv.decay);
else
noiseOut = 0;
}
#if AUDIO_FLOAT #if AUDIO_FLOAT
float curIn = pulseLookupTbl[p1Out + p2Out] + tndLookupTbl[(3*triOut) + (2*noiseOut) + dmcVol]; float curIn = apu.pulseLookupTbl[apu.p1Out + apu.p2Out] + apu.tndLookupTbl[(3*apu.triOut) + (2*apu.noiseOut) + apu.dmcVol];
//very rough still uint8_t ampVolPos = 0;
if(vrc6enabled) //very rough still
{ if(aExp & EXP_VRC6)
vrc6AudioCycle(); {
curIn += ((float)vrc6Out)*0.008f; vrc6AudioCycle();
curIn *= 0.6667f; curIn += ((float)vrc6Out)*0.008f;
} ampVolPos++;
if(fdsEnabled) }
{ if(aExp & EXP_FDS)
fdsAudioCycle(); {
curIn += ((float)fdsOut)*0.00617f; fdsAudioCycle();
curIn *= 0.75f; curIn += ((float)fdsOut)*0.00617f;
} ampVolPos++;
if(mmc5enabled) }
{ if(aExp & EXP_MMC5)
mmc5AudioCycle(); {
curIn += pulseLookupTbl[mmc5Out]+(mmc5pcm*0.002f); mmc5AudioCycle();
curIn *= 0.75f; curIn += apu.pulseLookupTbl[mmc5Out]+(mmc5pcm*0.002f);
} ampVolPos++;
if(vrc7enabled) }
{ if(aExp & EXP_VRC7)
curIn += (((float)(vrc7Out>>7))/32768.f); {
curIn *= 0.75f; curIn += (((float)(vrc7Out>>7))/32768.f);
} ampVolPos++;
if(n163enabled) }
{ if(aExp & EXP_N163)
curIn += ((float)n163Out)*0.0008f; {
curIn *= 0.6667f; curIn += ((float)n163Out)*0.0008f;
} ampVolPos++;
if(s5Benabled) }
{ if(aExp & EXP_S5B)
s5BAudioCycle(); {
curIn += ((float)s5BOut)/32768.f; s5BAudioCycle();
curIn *= 0.6667f; curIn += ((float)s5BOut)/32768.f;
} ampVolPos++;
//amplify input }
curIn *= 3.0f; //amplify input
float curLPout = lastLPOut+(lpVal*(curIn-lastLPOut)); curIn *= ampVol[ampVolPos];
float curHPOut = hpVal*(lastHPOut+lastLPOut-curLPout); float curLPout = apu.lastLPOut+(apu.lpVal*(curIn-apu.lastLPOut));
//set output float curHPOut = apu.hpVal*(apu.lastHPOut+apu.lastLPOut-curLPout);
apuOutBuf[curBufPos] = curHPOut; //set output
lastLPOut = curLPout; apu.OutBuf[apu.curBufPos] = curHPOut;
lastHPOut = curHPOut; apu.lastLPOut = curLPout;
apu.lastHPOut = curHPOut;
#else #else
int32_t curIn = pulseLookupTbl[p1Out + p2Out] + tndLookupTbl[(3*triOut) + (2*noiseOut) + dmcVol]; int32_t curIn = apu.pulseLookupTbl[apu.p1Out + apu.p2Out] + apu.tndLookupTbl[(3*apu.triOut) + (2*apu.noiseOut) + apu.dmcVol];
//very rough still uint8_t ampVolPos = 0;
if(vrc6enabled) //very rough still
{ if(aExp & EXP_VRC6)
vrc6AudioCycle(); {
curIn += ((int32_t)vrc6Out)*262; vrc6AudioCycle();
curIn <<= 1; curIn /= 3; curIn += ((int32_t)vrc6Out)*262;
} ampVolPos++;
if(fdsEnabled) }
{ if(aExp & EXP_FDS)
fdsAudioCycle(); {
curIn += ((int32_t)fdsOut)*202; fdsAudioCycle();
curIn *= 3; curIn >>= 2; curIn += ((int32_t)fdsOut)*202;
} ampVolPos++;
if(mmc5enabled) }
{ if(aExp & EXP_MMC5)
mmc5AudioCycle(); {
curIn += pulseLookupTbl[mmc5Out]+(mmc5pcm<<6); mmc5AudioCycle();
curIn *= 3; curIn >>= 2; curIn += apu.pulseLookupTbl[mmc5Out]+(mmc5pcm<<6);
} ampVolPos++;
if(vrc7enabled) }
{ if(aExp & EXP_VRC7)
curIn += vrc7Out>>7; {
curIn *= 3; curIn >>= 2; curIn += vrc7Out>>7;
} ampVolPos++;
if(n163enabled) }
{ if(aExp & EXP_N163)
curIn += n163Out*26; {
curIn <<= 1; curIn /= 3; curIn += n163Out*26;
} ampVolPos++;
if(s5Benabled) }
{ if(aExp & EXP_S5B)
s5BAudioCycle(); {
curIn += s5BOut; s5BAudioCycle();
curIn <<= 1; curIn /= 3; curIn += s5BOut;
} ampVolPos++;
//amplify input }
curIn *= 3; //amplify input
int32_t curOut; curIn *= apu.ampVol[ampVolPos];
//gen output int32_t curOut;
curOut = lastLPOut+((lpVal*(curIn-lastLPOut))>>15); //Set Lowpass Output //gen output
curIn = (lastHPOut+lastLPOut-curOut); //Set Highpass Input curOut = apu.lastLPOut+((apu.lpVal*((curIn>>6)-apu.lastLPOut))>>15); //Set Lowpass Output
curIn += (curIn>>31)&1; //Add Sign Bit for proper Downshift later curIn = (apu.lastHPOut+apu.lastLPOut-curOut); //Set Highpass Input
lastLPOut = curOut; //Save Lowpass Output curIn += (curIn>>31)&1; //Add Sign Bit for proper Downshift later
curOut = (hpVal*curIn)>>15; //Set Highpass Output apu.lastLPOut = curOut; //Save Lowpass Output
lastHPOut = curOut; //Save Highpass Output curOut = (apu.hpVal*curIn)>>15; //Set Highpass Output
//Save Clipped Highpass Output apu.lastHPOut = curOut; //Save Highpass Output
apuOutBuf[curBufPos] = (curOut > 32767)?(32767):((curOut < -32768)?(-32768):curOut); //Save Clipped Highpass Output
apu.OutBuf[apu.curBufPos] = (curOut > 32767)?(32767):((curOut < -32768)?(-32768):curOut);
#endif #endif
apuOutBuf[curBufPos+1] = apuOutBuf[curBufPos]; apu.OutBuf[apu.curBufPos+1] = apu.OutBuf[apu.curBufPos];
curBufPos+=2; apu.curBufPos+=2;
}
apu.apuClock++;
if(apu.p1freqCtr == 0)
{
apu.p1freqCtr = (apu.freq1<<1)+1;
apu.p1Cycle = (apu.p1Cycle+1)&7;
}
else
apu.p1freqCtr--;
if(apu.p2freqCtr == 0)
{
apu.p2freqCtr = (apu.freq2<<1)+1;
apu.p2Cycle = (apu.p2Cycle+1)&7;
}
else
apu.p2freqCtr--;
if(apu.triFreqCtr == 0)
{
apu.triFreqCtr = apu.triFreq;
apu.triCycle = (apu.triCycle+1)&31;
}
else
apu.triFreqCtr--;
if(apu.noiseFreqCtr == 0)
{
apu.noiseFreqCtr = apu.noiseFreq;
uint8_t cmpBit = apu.noiseMode1 ? (apu.noiseShiftReg>>6)&1 : (apu.noiseShiftReg>>1)&1;
uint8_t cmpRes = (apu.noiseShiftReg&1)^cmpBit;
apu.noiseShiftReg >>= 1;
apu.noiseShiftReg |= cmpRes<<14;
}
else
apu.noiseFreqCtr--;
if(apu.dmcFreqCtr == 0)
{
apu.dmcFreqCtr = apu.dmcFreq;
if(apu.dmcenabled)
{
if(apu.dmcSampleBuf&1)
{
if(apu.dmcVol <= 125)
apu.dmcVol += 2;
}
else if(apu.dmcVol >= 2)
apu.dmcVol -= 2;
apu.dmcSampleBuf>>=1;
}
if(apu.dmcSampleRemain == 0)
{
if(apu.dmcready)
{
apu.dmcSampleBuf = apu.dmcCpuBuf;
apu.dmcenabled = true;
apu.dmcready = false;
}
else
apu.dmcenabled = false;
apu.dmcSampleRemain = 7;
}
else
apu.dmcSampleRemain--;
}
else
apu.dmcFreqCtr--;
if(!apu.dmcready && !cpuInDMC_DMA() && apu.dmcCurLen)
{
cpuDoDMC_DMA(apu.dmcCurAddr);
apu.dmcCurLen--;
}
if(aExp&EXP_VRC7)
{
if(apu.vrc7Clock == vrc7CycleTimer)
{
vrc7AudioCycle();
apu.vrc7Clock = 1;
}
else
apu.vrc7Clock++;
}
if(aExp&EXP_FDS)
fdsAudioMasterUpdate();
if(aExp&EXP_MMC5)
mmc5AudioLenCycle();
if(apu.mode_change)
apuChangeMode();
if(apu.mode5 == false)
{
if(apu.modeCurCtr == 0)
{
if(apu.modePos == 5)
apu.modePos = 0;
else
apu.modePos++;
apu.modeCurCtr = apu.mode4Ctr[apu.modePos]-1;
if(apu.modePos == 3 || apu.modePos == 5)
{
if(apu.enable_irq)
apu.irq = 1;
}
else
{
if(apu.modePos == 1)
apuClockA();
else if(apu.modePos == 4)
{
apuClockA();
if(apu.enable_irq)
{
apu.irq = 1;
//actually set for cpu
interrupt |= APU_IRQ;
}
}
apuClockB();
}
}
else
apu.modeCurCtr--;
}
else
{
if(apu.modeCurCtr == 0)
{
if(apu.modePos == 5)
apu.modePos = 0;
else
apu.modePos++;
apu.modeCurCtr = apu.mode5Ctr[apu.modePos]-1;
if(apu.modePos != 1 && apu.modePos != 5)
{
if(apu.modePos == 0 || apu.modePos == 3)
apuClockA();
apuClockB();
}
}
else
apu.modeCurCtr--;
}
return true; return true;
} }

@ -1 +1 @@
Subproject commit 01b5bde49a730eb287b18def7ed5e5f510cda7b5 Subproject commit 03b5b7fdf32708dd83e13224747fe3a387dafa69

View File

@ -4,5 +4,5 @@
uint8_t* ppuGetVRAM() uint8_t* ppuGetVRAM()
{ {
return PPU_VRAM; return ppu.VRAM;
} }

View File

@ -625,6 +625,8 @@ kabufuda::SystemString CMemoryCardSys::CreateDolphinCard(kabufuda::ECardSlot slo
CardProbe(slot); CardProbe(slot);
MountCard(slot); MountCard(slot);
FormatCard(slot); FormatCard(slot);
kabufuda::Card& card = g_CardStates[int(slot)];
card.waitForCompletion();
return path; return path;
} }

View File

@ -2016,7 +2016,7 @@ CFrontEndUI::CFrontEndUI()
m_touchBar = NewFrontEndUITouchBar(); m_touchBar = NewFrontEndUITouchBar();
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None); m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
x14_phase = EPhase::ExitFrontEnd; //x14_phase = EPhase::ExitFrontEnd;
} }
void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue) void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue)

@ -1 +1 @@
Subproject commit 0c012a37767960fada314965d46f519825c8c96d Subproject commit 37461f2165d2ebe94871ceef22fbea5b6044cf20