mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2024-06-22 06:02:26 -04:00
Merge improvements from upstream core
This commit is contained in:
parent
f631ba0d16
commit
da5ac83f17
|
@ -13,11 +13,15 @@ Core:
|
|||
- Use Nestopia core from jgemu
|
||||
|
||||
Fixes:
|
||||
- Timing and other accuracy fixes
|
||||
- Timing and other accuracy fixes for CPU/APU
|
||||
- Revert changes that caused regressions
|
||||
- Fix Camerica mapper for Dooly Bravo Land
|
||||
- Improve MMC5 emulation for Sim City
|
||||
- Fix 8K PRG NROM games such as Galaxian
|
||||
- Full implementation of mapper 156
|
||||
- Fix SOROM saving/loading
|
||||
- Fix FDS IRQ behaviour
|
||||
- Improve RAMBO-1 timing
|
||||
|
||||
----------------------------------------------------------------
|
||||
1.50
|
||||
|
|
|
@ -373,7 +373,7 @@ namespace Nes
|
|||
{
|
||||
State::Loader::Data<4> data( state );
|
||||
|
||||
io.ctrl = data[0];
|
||||
io.ctrl = adapter.ctrl = data[0];
|
||||
io.port = data[1];
|
||||
break;
|
||||
}
|
||||
|
@ -550,7 +550,13 @@ namespace Nes
|
|||
|
||||
NES_POKE_D(Fds,4023)
|
||||
{
|
||||
io.ctrl = data;
|
||||
io.ctrl = adapter.ctrl = data;
|
||||
|
||||
if (!(io.ctrl & Io::CTRL0_DISK_ENABLED))
|
||||
{
|
||||
cpu.ClearIRQ();
|
||||
adapter.DisableIRQ();
|
||||
}
|
||||
}
|
||||
|
||||
NES_POKE_D(Fds,4026)
|
||||
|
@ -783,21 +789,25 @@ namespace Nes
|
|||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
void Fds::Unit::Timer::Advance(uint& timer)
|
||||
bool Fds::Unit::Timer::Clock()
|
||||
{
|
||||
timer |= STATUS_PENDING_IRQ;
|
||||
bool retval = false;
|
||||
|
||||
if (ctrl & CTRL_REPEAT)
|
||||
count = latch;
|
||||
else
|
||||
ctrl &= ~uint(CTRL_ENABLED);
|
||||
|
||||
latch = 0; // Fixes Kaettekita Mario Bros - FHorse/dragon2snow
|
||||
}
|
||||
if (ctrl & CTRL_ENABLED)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
retval = true;
|
||||
count = latch;
|
||||
|
||||
NST_SINGLE_CALL bool Fds::Unit::Timer::Clock()
|
||||
{
|
||||
return !(ctrl & CTRL_ENABLED) || !count || --count;
|
||||
if (!(ctrl & CTRL_REPEAT))
|
||||
ctrl &= ~uint(CTRL_ENABLED);
|
||||
}
|
||||
else
|
||||
count--;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
|
@ -1202,11 +1212,15 @@ namespace Nes
|
|||
|
||||
ibool Fds::Unit::Clock()
|
||||
{
|
||||
return
|
||||
(
|
||||
(timer.Clock() ? 0 : (timer.Advance(status), 1)) |
|
||||
(drive.Clock() ? 0 : drive.Advance(status))
|
||||
);
|
||||
bool retval = false;
|
||||
|
||||
if (timer.Clock())
|
||||
{
|
||||
status |= STATUS_PENDING_IRQ;
|
||||
retval = true;
|
||||
}
|
||||
|
||||
return (retval | (drive.Clock() ? 0 : drive.Advance(status)));
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
|
@ -1216,6 +1230,12 @@ namespace Nes
|
|||
Fds::Adapter::Adapter(Cpu& c,const Disks::Sides& s)
|
||||
: Timer::M2<Unit>(c,s) {}
|
||||
|
||||
void Fds::Adapter::DisableIRQ()
|
||||
{
|
||||
unit.status &= ~uint(Unit::STATUS_PENDING_IRQ);
|
||||
unit.timer.ctrl &= ~uint(Unit::Timer::CTRL_ENABLED);
|
||||
}
|
||||
|
||||
void Fds::Adapter::Reset(Cpu& cpu,byte* const io,bool protect)
|
||||
{
|
||||
Timer::M2<Unit>::Reset( true, true );
|
||||
|
@ -1379,12 +1399,17 @@ namespace Nes
|
|||
{
|
||||
Update();
|
||||
|
||||
if (!(ctrl & Io::CTRL0_DISK_ENABLED))
|
||||
return;
|
||||
|
||||
unit.timer.ctrl = data;
|
||||
unit.timer.count = unit.timer.latch;
|
||||
unit.status &= Unit::STATUS_TRANSFERED;
|
||||
|
||||
if (!unit.status)
|
||||
ClearIRQ();
|
||||
if (data & Unit::Timer::CTRL_ENABLED)
|
||||
return;
|
||||
|
||||
ClearIRQ();
|
||||
}
|
||||
|
||||
NES_POKE_D(Fds::Adapter,4024)
|
||||
|
|
|
@ -340,7 +340,6 @@ namespace Nes
|
|||
Timer();
|
||||
|
||||
void Reset();
|
||||
void Advance(uint&);
|
||||
|
||||
NST_SINGLE_CALL bool Clock();
|
||||
|
||||
|
@ -435,6 +434,7 @@ namespace Nes
|
|||
|
||||
Adapter(Cpu&,const Disks::Sides&);
|
||||
|
||||
void DisableIRQ();
|
||||
void Reset(Cpu&,byte*,bool=false);
|
||||
void LoadState(State::Loader&,dword,Ppu&);
|
||||
void SaveState(State::Saver&) const;
|
||||
|
@ -447,6 +447,8 @@ namespace Nes
|
|||
NST_SINGLE_CALL uint Activity() const;
|
||||
|
||||
using Timer::M2<Unit>::VSync;
|
||||
|
||||
byte ctrl;
|
||||
};
|
||||
|
||||
struct Io
|
||||
|
|
|
@ -397,7 +397,16 @@ namespace Nes
|
|||
{
|
||||
wrk.Source().SetSecurity( true, board.GetWram() > 0 );
|
||||
|
||||
for (uint i=board.GetSavableWram(), n=board.GetWram(); i < n; ++i)
|
||||
uint i = board.GetSavableWram();
|
||||
uint n = board.GetWram();
|
||||
|
||||
if (board.GetMapper() == 1 && board.GetWram() == SIZE_16K)
|
||||
{
|
||||
i = 0;
|
||||
n = SIZE_8K;
|
||||
}
|
||||
|
||||
for (; i < n; ++i)
|
||||
*wrk.Source().Mem(i) = (board.IsAutoWram() && i < SIZE_8K) ? (0x6000 + i) >> 8 : 0x00;
|
||||
|
||||
vram.Fill( 0x00 );
|
||||
|
|
|
@ -468,7 +468,7 @@ namespace Nes
|
|||
// Nihon Bussan
|
||||
NIHON_UNROM_M5 = MakeId< 180, 128, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
|
||||
// Open Corp
|
||||
OPENCORP_DAOU306 = MakeId< 156, 256, 256, 8, 0, CRM_0, NMT_1, 0 >::ID,
|
||||
OPENCORP_DAOU306 = MakeId< 156, 256, 512, 8, 0, CRM_0, NMT_1, 0 >::ID,
|
||||
// RCM
|
||||
RCM_GS2004 = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
|
||||
RCM_GS2013 = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_X, 1 >::ID,
|
||||
|
|
|
@ -153,7 +153,12 @@ namespace Nes
|
|||
void Vrc2::SwapChr(uint address,uint subBank) const
|
||||
{
|
||||
ppu.Update();
|
||||
chr.SwapBank<SIZE_1K>( address, (chr.GetBank<SIZE_1K>(address) & 0xF0U >> OFFSET) | ((subBank >> chrShift & 0xF) << OFFSET) );
|
||||
|
||||
chr.SwapBank<SIZE_1K>( address, chrShift ? OFFSET ?
|
||||
(chr.GetBank<SIZE_1K>(address) & 0x07U) | ((subBank & 0xFU) << 3) :
|
||||
(chr.GetBank<SIZE_1K>(address) & 0xF8U) | ((subBank >> 1) & 0x7U) :
|
||||
(chr.GetBank<SIZE_1K>(address) & 0xF0U >> OFFSET) | ((subBank & 0xFU) << OFFSET)
|
||||
);
|
||||
}
|
||||
|
||||
NES_POKE_D(Vrc2,B000) { SwapChr<0>( 0x0000, data ); }
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "../NstLog.hpp"
|
||||
#include "NstBoard.hpp"
|
||||
#include "NstBoardMmc1.hpp"
|
||||
#include "../NstFile.hpp"
|
||||
|
||||
namespace Nes
|
||||
{
|
||||
|
@ -119,6 +120,20 @@ namespace Nes
|
|||
#pragma optimize("", on)
|
||||
#endif
|
||||
|
||||
void Mmc1::Save(File& file) const
|
||||
{
|
||||
uint offset = (board.GetWram() == SIZE_16K) ? SIZE_8K : 0; // SOROM
|
||||
if (board.HasBattery() && board.GetSavableWram())
|
||||
file.Save( File::BATTERY, wrk.Source().Mem(offset), board.GetSavableWram() );
|
||||
}
|
||||
|
||||
void Mmc1::Load(File& file)
|
||||
{
|
||||
uint offset = (board.GetWram() == SIZE_16K) ? SIZE_8K : 0; // SOROM
|
||||
if (board.HasBattery() && board.GetSavableWram())
|
||||
file.Load( File::BATTERY, wrk.Source().Mem(offset), board.GetSavableWram() );
|
||||
}
|
||||
|
||||
void Mmc1::UpdatePrg()
|
||||
{
|
||||
prg.SwapBanks<SIZE_16K,0x0000>
|
||||
|
|
|
@ -82,6 +82,9 @@ namespace Nes
|
|||
|
||||
private:
|
||||
|
||||
void Save(File&) const;
|
||||
void Load(File&);
|
||||
|
||||
void ResetRegisters();
|
||||
virtual void NST_FASTCALL UpdateRegisters(uint);
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Reference: https://github.com/TASVideos/fceux/blob/master/src/boards/156.cpp
|
||||
|
||||
#include "NstBoard.hpp"
|
||||
#include "NstBoardOpenCorp.hpp"
|
||||
|
||||
|
@ -37,17 +39,139 @@ namespace Nes
|
|||
#pragma optimize("s", on)
|
||||
#endif
|
||||
|
||||
void Daou306::RemapChr()
|
||||
{
|
||||
chr.SwapBank<SIZE_1K>( 0x0000, (chrHigh[0] << 8) | chrLow[0] );
|
||||
chr.SwapBank<SIZE_1K>( 0x0400, (chrHigh[1] << 8) | chrLow[1] );
|
||||
chr.SwapBank<SIZE_1K>( 0x0800, (chrHigh[2] << 8) | chrLow[2] );
|
||||
chr.SwapBank<SIZE_1K>( 0x0C00, (chrHigh[3] << 8) | chrLow[3] );
|
||||
chr.SwapBank<SIZE_1K>( 0x1000, (chrHigh[4] << 8) | chrLow[4] );
|
||||
chr.SwapBank<SIZE_1K>( 0x1400, (chrHigh[5] << 8) | chrLow[5] );
|
||||
chr.SwapBank<SIZE_1K>( 0x1800, (chrHigh[6] << 8) | chrLow[6] );
|
||||
chr.SwapBank<SIZE_1K>( 0x1C00, (chrHigh[7] << 8) | chrLow[7] );
|
||||
|
||||
if (mirrorUsed) {
|
||||
ppu.SetMirroring( mirror ^ 0x1 ? Ppu::NMT_V : Ppu::NMT_H );
|
||||
}
|
||||
else
|
||||
{
|
||||
ppu.SetMirroring( Ppu::NMT_0 );
|
||||
}
|
||||
}
|
||||
|
||||
void Daou306::SubReset(bool)
|
||||
{
|
||||
Map( 0xC000U, CHR_SWAP_1K_0 );
|
||||
Map( 0xC001U, CHR_SWAP_1K_1 );
|
||||
Map( 0xC002U, CHR_SWAP_1K_2 );
|
||||
Map( 0xC003U, CHR_SWAP_1K_3 );
|
||||
Map( 0xC008U, CHR_SWAP_1K_4 );
|
||||
Map( 0xC009U, CHR_SWAP_1K_5 );
|
||||
Map( 0xC00AU, CHR_SWAP_1K_6 );
|
||||
Map( 0xC00BU, CHR_SWAP_1K_7 );
|
||||
for (uint i = 0; i < 8; i++)
|
||||
{
|
||||
chrLow[i] = chrHigh[i] = 0;
|
||||
}
|
||||
|
||||
Map( 0xC000U, 0xC00FU, &Daou306::Poke_C000 );
|
||||
Map( 0xC010U, PRG_SWAP_16K_0 );
|
||||
Map( 0xC014U, &Daou306::Poke_C014 );
|
||||
}
|
||||
|
||||
NES_POKE_AD(Daou306,C000)
|
||||
{
|
||||
switch (address)
|
||||
{
|
||||
case 0xC000:
|
||||
case 0xC001:
|
||||
case 0xC002:
|
||||
case 0xC003:
|
||||
chrLow[address & 0x03] = data;
|
||||
break;
|
||||
case 0xC004:
|
||||
case 0xC005:
|
||||
case 0xC006:
|
||||
case 0xC007:
|
||||
chrHigh[address & 0x03] = data;
|
||||
break;
|
||||
case 0xC008:
|
||||
case 0xC009:
|
||||
case 0xC00A:
|
||||
case 0xC00B:
|
||||
chrLow[4 + (address & 0x03)] = data;
|
||||
break;
|
||||
case 0xC00C:
|
||||
case 0xC00D:
|
||||
case 0xC00E:
|
||||
case 0xC00F:
|
||||
chrHigh[4 + (address & 0x03)] = data;
|
||||
break;
|
||||
}
|
||||
RemapChr();
|
||||
}
|
||||
|
||||
NES_POKE_D(Daou306,C014)
|
||||
{
|
||||
mirror = data;
|
||||
mirrorUsed = 1;
|
||||
}
|
||||
|
||||
void Daou306::SubLoad(State::Loader& state,const dword baseChunk)
|
||||
{
|
||||
NST_VERIFY( baseChunk == (AsciiId<'O','P','C'>::V) );
|
||||
|
||||
if (baseChunk == AsciiId<'O','P','C'>::V)
|
||||
{
|
||||
state.Begin();
|
||||
|
||||
State::Loader::Data<18> data( state );
|
||||
chrLow[0] = data[0];
|
||||
chrLow[1] = data[1];
|
||||
chrLow[2] = data[2];
|
||||
chrLow[3] = data[3];
|
||||
chrLow[4] = data[4];
|
||||
chrLow[5] = data[5];
|
||||
chrLow[6] = data[6];
|
||||
chrLow[7] = data[7];
|
||||
chrHigh[0] = data[8];
|
||||
chrHigh[1] = data[9];
|
||||
chrHigh[2] = data[10];
|
||||
chrHigh[3] = data[11];
|
||||
chrHigh[4] = data[12];
|
||||
chrHigh[5] = data[13];
|
||||
chrHigh[6] = data[14];
|
||||
chrHigh[7] = data[15];
|
||||
mirror = data[16];
|
||||
mirrorUsed = data[17];
|
||||
|
||||
state.End();
|
||||
|
||||
RemapChr();
|
||||
}
|
||||
}
|
||||
|
||||
void Daou306::SubSave(State::Saver& state) const
|
||||
{
|
||||
state.Begin( AsciiId<'O','P','C'>::V );
|
||||
|
||||
const byte data[18] =
|
||||
{
|
||||
chrLow[0],
|
||||
chrLow[1],
|
||||
chrLow[2],
|
||||
chrLow[3],
|
||||
chrLow[4],
|
||||
chrLow[5],
|
||||
chrLow[6],
|
||||
chrLow[7],
|
||||
chrHigh[0],
|
||||
chrHigh[1],
|
||||
chrHigh[2],
|
||||
chrHigh[3],
|
||||
chrHigh[4],
|
||||
chrHigh[5],
|
||||
chrHigh[6],
|
||||
chrHigh[7],
|
||||
mirror,
|
||||
mirrorUsed,
|
||||
};
|
||||
|
||||
state.Begin( AsciiId<'C','H','R'>::V ).Write( data ).End();
|
||||
|
||||
state.End();
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
|
|
|
@ -46,7 +46,18 @@ namespace Nes
|
|||
|
||||
private:
|
||||
|
||||
byte chrLow[8];
|
||||
byte chrHigh[8];
|
||||
byte mirror;
|
||||
byte mirrorUsed;
|
||||
|
||||
void RemapChr();
|
||||
void SubReset(bool);
|
||||
void SubSave(State::Saver&) const;
|
||||
void SubLoad(State::Loader&,dword);
|
||||
|
||||
NES_DECL_POKE( C000 );
|
||||
NES_DECL_POKE( C014 );
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,7 +322,7 @@ namespace Nes
|
|||
ctrl = data[0] >> 1 & 0x1F;
|
||||
length = data[1] | (data[2] << 8 & 0xF00);
|
||||
volume = levels[(ctrl & 0xF) ? (ctrl & 0xF) * 2 + 1 : 0];
|
||||
dc = (status & 0x1) ? ~0UL : 0UL;
|
||||
dc = (status & 0x1) ? ~dword(0) : dword(0);
|
||||
|
||||
UpdateSettings( fixed );
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Nes
|
|||
if (hard)
|
||||
{
|
||||
count = 0;
|
||||
cycles = 0;
|
||||
reload = false;
|
||||
latch = 0;
|
||||
enabled = false;
|
||||
|
@ -121,14 +122,16 @@ namespace Nes
|
|||
|
||||
case AsciiId<'I','R','Q'>::V:
|
||||
{
|
||||
State::Loader::Data<3> data( state );
|
||||
State::Loader::Data<4> data( state );
|
||||
|
||||
irq.unit.enabled = data[0] & 0x1;
|
||||
irq.unit.mode = data[0] & 0x2 ? 1 : 0;
|
||||
irq.a12.Connect( data[0] & 0x2 );
|
||||
irq.m2.Connect( data[0] & 0x2 );
|
||||
irq.unit.reload = data[0] & 0x4;
|
||||
irq.unit.latch = data[1];
|
||||
irq.unit.count = data[2];
|
||||
irq.unit.cycles = data[3];
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -164,13 +167,14 @@ namespace Nes
|
|||
}
|
||||
|
||||
{
|
||||
const byte data[3] =
|
||||
const byte data[4] =
|
||||
{
|
||||
(irq.unit.enabled ? 0x1U : 0x0U) |
|
||||
(irq.m2.Connected() ? 0x2U : 0x0U) |
|
||||
(irq.unit.reload ? 0x4U : 0x0U),
|
||||
irq.unit.latch,
|
||||
irq.unit.count & 0xFF
|
||||
irq.unit.count & 0xFF,
|
||||
irq.unit.cycles,
|
||||
};
|
||||
|
||||
state.Begin( AsciiId<'I','R','Q'>::V ).Write( data ).End();
|
||||
|
@ -185,47 +189,33 @@ namespace Nes
|
|||
|
||||
bool Rambo1::Irq::Unit::Clock()
|
||||
{
|
||||
/*if (!reload)
|
||||
cycles++;
|
||||
|
||||
if (reload)
|
||||
{
|
||||
if (count)
|
||||
{
|
||||
return !--count && enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = latch;
|
||||
return false;
|
||||
}
|
||||
reload = false;
|
||||
count = latch | (latch ? 1 : 0);
|
||||
|
||||
if (mode)
|
||||
count |= 2;
|
||||
|
||||
if (!latch && cycles > A12_FILTER)
|
||||
count = 1;
|
||||
|
||||
cycles = 0;
|
||||
}
|
||||
else if (!count)
|
||||
{
|
||||
count = latch;
|
||||
if (cycles > A12_FILTER)
|
||||
cycles = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
reload = false;
|
||||
count = latch + 1;
|
||||
return false;
|
||||
}*/
|
||||
|
||||
// From dragon2snow
|
||||
if (reload) {
|
||||
if (latch < 1) {
|
||||
count = latch + 1;
|
||||
}
|
||||
else {
|
||||
count = latch + 2;
|
||||
}
|
||||
reload = false;
|
||||
count--;
|
||||
}
|
||||
else if (!count) {
|
||||
count = latch + 1;
|
||||
}
|
||||
|
||||
count--;
|
||||
|
||||
if (!count && enabled) {
|
||||
/* wait one M2 cycle, then trigger IRQ */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
return (!count && enabled);
|
||||
}
|
||||
|
||||
void Rambo1::Irq::Update()
|
||||
|
@ -320,6 +310,7 @@ namespace Nes
|
|||
{
|
||||
irq.Update();
|
||||
irq.unit.latch = data;
|
||||
irq.unit.mode = irq.m2.Connected();
|
||||
}
|
||||
|
||||
NES_POKE_D(Rambo1,C001)
|
||||
|
|
|
@ -95,9 +95,11 @@ namespace Nes
|
|||
bool Clock();
|
||||
|
||||
uint count;
|
||||
uint cycles;
|
||||
uint latch;
|
||||
ibool reload;
|
||||
ibool enabled;
|
||||
ibool mode;
|
||||
};
|
||||
|
||||
typedef Timer::A12<Unit&,A12_FILTER,IRQ_DELAY> A12;
|
||||
|
|
Loading…
Reference in a new issue