wyatt8740

NstPpu.cpp

Apr 6th, 2015
530
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 65.06 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Nestopia - NES/Famicom emulator written in C++
  4. //
  5. // Copyright (C) 2003-2008 Martin Freij
  6. //
  7. // This file is part of Nestopia.
  8. //
  9. // Nestopia is free software; you can redistribute it and/or modify
  10. // it under the terms of the GNU General Public License as published by
  11. // the Free Software Foundation; either version 2 of the License, or
  12. // (at your option) any later version.
  13. //
  14. // Nestopia is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17. // GNU General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public License
  20. // along with Nestopia; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22. //
  23. ////////////////////////////////////////////////////////////////////////////////////////
  24.  
  25. #include <cstring>
  26. #include "NstCpu.hpp"
  27. #include "NstPpu.hpp"
  28. #include "NstState.hpp"
  29.  
  30. namespace Nes
  31. {
  32.     namespace Core
  33.     {
  34.         #ifdef NST_MSVC_OPTIMIZE
  35.         #pragma optimize("s", on)
  36.         #endif
  37.  
  38.         const byte Ppu::yuvMaps[4][0x40] =
  39.         {
  40.             {
  41.                 0x35, 0x23, 0x16, 0x22, 0x1C, 0x09, 0x2D, 0x15,
  42.                 0x20, 0x00, 0x27, 0x05, 0x04, 0x28, 0x08, 0x20,
  43.                 0x21, 0x27, 0x07, 0x29, 0x3C, 0x32, 0x36, 0x12,
  44.                 0x28, 0x2B, 0x0D, 0x08, 0x10, 0x3D, 0x24, 0x01,
  45.                 0x01, 0x31, 0x33, 0x2A, 0x2C, 0x0C, 0x1B, 0x14,
  46.                 0x0D, 0x07, 0x34, 0x06, 0x13, 0x02, 0x26, 0x0D,
  47.                 0x0D, 0x19, 0x10, 0x0A, 0x39, 0x03, 0x37, 0x17,
  48.                 0x09, 0x11, 0x1A, 0x1D, 0x38, 0x25, 0x18, 0x3A
  49.             },
  50.             {
  51.                 0x0D, 0x27, 0x18, 0x39, 0x3A, 0x25, 0x1C, 0x31,
  52.                 0x16, 0x13, 0x38, 0x34, 0x20, 0x23, 0x3C, 0x1A,
  53.                 0x09, 0x21, 0x06, 0x10, 0x1B, 0x29, 0x08, 0x22,
  54.                 0x2D, 0x24, 0x01, 0x2B, 0x32, 0x08, 0x0D, 0x03,
  55.                 0x04, 0x36, 0x26, 0x33, 0x11, 0x07, 0x10, 0x02,
  56.                 0x14, 0x28, 0x00, 0x09, 0x12, 0x0D, 0x28, 0x20,
  57.                 0x27, 0x1D, 0x2A, 0x17, 0x0C, 0x01, 0x15, 0x19,
  58.                 0x0D, 0x2C, 0x07, 0x37, 0x35, 0x05, 0x0A, 0x3D
  59.             },
  60.             {
  61.                 0x14, 0x25, 0x3A, 0x10, 0x1A, 0x20, 0x31, 0x09,
  62.                 0x01, 0x0D, 0x36, 0x08, 0x15, 0x10, 0x27, 0x3C,
  63.                 0x22, 0x1C, 0x05, 0x12, 0x19, 0x18, 0x17, 0x1B,
  64.                 0x00, 0x03, 0x0D, 0x02, 0x16, 0x06, 0x34, 0x35,
  65.                 0x23, 0x09, 0x01, 0x37, 0x1D, 0x27, 0x26, 0x20,
  66.                 0x29, 0x04, 0x21, 0x24, 0x11, 0x3D, 0x0D, 0x07,
  67.                 0x2C, 0x08, 0x39, 0x33, 0x07, 0x2A, 0x28, 0x2D,
  68.                 0x0A, 0x0D, 0x32, 0x38, 0x13, 0x2B, 0x28, 0x0C
  69.             },
  70.             {
  71.                 0x18, 0x03, 0x1C, 0x28, 0x0D, 0x35, 0x01, 0x17,
  72.                 0x10, 0x07, 0x2A, 0x01, 0x36, 0x37, 0x1A, 0x39,
  73.                 0x25, 0x08, 0x12, 0x34, 0x0D, 0x2D, 0x06, 0x26,
  74.                 0x27, 0x1B, 0x22, 0x19, 0x04, 0x0D, 0x3A, 0x21,
  75.                 0x05, 0x0A, 0x07, 0x02, 0x13, 0x14, 0x00, 0x15,
  76.                 0x0C, 0x10, 0x11, 0x09, 0x1D, 0x38, 0x3D, 0x24,
  77.                 0x33, 0x20, 0x08, 0x16, 0x28, 0x2B, 0x20, 0x3C,
  78.                 0x0D, 0x27, 0x23, 0x31, 0x29, 0x32, 0x2C, 0x09
  79.             }
  80.         };
  81.  
  82.         Ppu::Tiles::Tiles()
  83.         : padding0(0), padding1(0) {}
  84.  
  85.         Ppu::Oam::Oam()
  86.         : limit(buffer + STD_LINE_SPRITES*4), spriteLimit(true) {}
  87.  
  88.         Ppu::Output::Output(Video::Screen::Pixel* p)
  89.         : pixels(p) {}
  90.  
  91.         Ppu::TileLut::TileLut()
  92.         {
  93.             for (uint i=0; i < 0x400; ++i)
  94.             {
  95.                 block[i][0] = (i & 0xC0) ? (i >> 6 & 0xC) | (i >> 6 & 0x3) : 0;
  96.                 block[i][1] = (i & 0x30) ? (i >> 6 & 0xC) | (i >> 4 & 0x3) : 0;
  97.                 block[i][2] = (i & 0x0C) ? (i >> 6 & 0xC) | (i >> 2 & 0x3) : 0;
  98.                 block[i][3] = (i & 0x03) ? (i >> 6 & 0xC) | (i >> 0 & 0x3) : 0;
  99.             }
  100.         }
  101.  
  102.         Ppu::Ppu(Cpu& c)
  103.         :
  104.         cpu    (c),
  105.         output (screen.pixels),
  106.         model  (PPU_RP2C02),
  107.         rgbMap (NULL),
  108.         yuvMap (NULL)
  109.         {
  110.             cycles.one = PPU_RP2C02_CC;
  111.             PowerOff();
  112.         }
  113.  
  114.         void Ppu::PowerOff()
  115.         {
  116.             Reset( true, false, false );
  117.         }
  118.  
  119.         void Ppu::Reset(bool hard,bool acknowledged)
  120.         {
  121.             Reset( hard, acknowledged, true );
  122.         }
  123.  
  124.         void Ppu::Reset(const bool hard,const bool acknowledged,const bool map)
  125.         {
  126.             if (map)
  127.             {
  128.                 for (uint i=0x2000; i < 0x4000; i += 0x8)
  129.                 {
  130.                     cpu.Map( i+0 ).Set( this, i != 0x3000 ? &Ppu::Peek_2xxx : &Ppu::Peek_3000, &Ppu::Poke_2000 );
  131.                     cpu.Map( i+1 ).Set( this,               &Ppu::Peek_2xxx,                   &Ppu::Poke_2001 );
  132.                     cpu.Map( i+2 ).Set( this,               &Ppu::Peek_2002,                   &Ppu::Poke_2xxx );
  133.                     cpu.Map( i+3 ).Set( this,               &Ppu::Peek_2xxx,                   &Ppu::Poke_2003 );
  134.                     cpu.Map( i+4 ).Set( this,               &Ppu::Peek_2004,                   &Ppu::Poke_2004 );
  135.                     cpu.Map( i+5 ).Set( this,               &Ppu::Peek_2xxx,                   &Ppu::Poke_2005 );
  136.                     cpu.Map( i+6 ).Set( this,               &Ppu::Peek_2xxx,                   &Ppu::Poke_2006 );
  137.                     cpu.Map( i+7 ).Set( this,               &Ppu::Peek_2007,                   &Ppu::Poke_2007 );
  138.                 }
  139.  
  140.                 switch (model)
  141.                 {
  142.                     case PPU_RC2C05_01:
  143.                     case PPU_RC2C05_02:
  144.                     case PPU_RC2C05_03:
  145.                     case PPU_RC2C05_04:
  146.  
  147.                         if (model == PPU_RC2C05_02)
  148.                         {
  149.                             for (uint i=0x2002; i < 0x4000; i += 0x8)
  150.                                 cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_02 );
  151.                         }
  152.                         else if (model == PPU_RC2C05_03)
  153.                         {
  154.                             for (uint i=0x2002; i < 0x4000; i += 0x8)
  155.                                 cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_03 );
  156.                         }
  157.                         else
  158.                         {
  159.                             for (uint i=0x2002; i < 0x4000; i += 0x8)
  160.                                 cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_01_04 );
  161.                         }
  162.  
  163.                     case PPU_RC2C05_05:
  164.  
  165.                         for (uint i=0x2000; i < 0x4000; i += 0x8)
  166.                         {
  167.                             cpu.Map( i+0 ).Set( &Ppu::Poke_2001 );
  168.                             cpu.Map( i+1 ).Set( &Ppu::Poke_2000 );
  169.                         }
  170.                         break;
  171.                 }
  172.  
  173.                 cpu.Map( 0x4014U ).Set( this, &Ppu::Peek_4014, &Ppu::Poke_4014 );
  174.             }
  175.  
  176.             if (hard)
  177.             {
  178.                 static const byte powerUpPalette[] =
  179.                 {
  180.                     0x3F,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,
  181.                     0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
  182.                     0x09,0x01,0x34,0x03,0x00,0x04,0x00,0x14,
  183.                     0x08,0x3A,0x00,0x02,0x00,0x20,0x2C,0x08
  184.                 };
  185.  
  186.                 std::memcpy( palette.ram, powerUpPalette, Palette::SIZE );
  187.                 std::memset( oam.ram, Oam::GARBAGE, Oam::SIZE );
  188.                 std::memset( nameTable.ram, NameTable::GARBAGE, NameTable::SIZE );
  189.  
  190.                 io.latch = 0;
  191.                 io.buffer = Io::BUFFER_GARBAGE;
  192.  
  193.                 regs.status = 0;
  194.                 regs.ctrl[0] = 0;
  195.                 regs.ctrl[1] = 0;
  196.                 regs.frame = 0;
  197.                 regs.oam = 0;
  198.  
  199.                 scroll.latch = 0;
  200.                 scroll.xFine = 0;
  201.                 scroll.toggle = 0;
  202.                 scroll.address = 0;
  203.  
  204.                 output.burstPhase = 0;
  205.  
  206.                 cycles.reset = 0;
  207.                 cycles.hClock = HCLOCK_BOOT;
  208.             }
  209.             else if (acknowledged)
  210.             {
  211.                 io.buffer = 0;
  212.  
  213.                 regs.status = 0;
  214.                 regs.ctrl[0] = 0;
  215.                 regs.ctrl[1] = 0;
  216.  
  217.                 scroll.latch = 0;
  218.                 scroll.xFine = 0;
  219.                 scroll.toggle = 0;
  220.  
  221.                 cycles.reset = Cpu::CYCLE_MAX;
  222.                 cycles.hClock = HCLOCK_BOOT;
  223.  
  224.                 std::memset( oam.ram, Oam::GARBAGE, Oam::SIZE );
  225.             }
  226.             else
  227.             {
  228.                 cycles.hClock = HCLOCK_DUMMY;
  229.                 cycles.reset = 0;
  230.             }
  231.  
  232.             if (chr.Source().Empty())
  233.             {
  234.                 chr.Source().Set( Ram::RAM, true, false, NameTable::SIZE, nameTable.ram );
  235.                 chr.SwapBanks<SIZE_2K,0x0000>(0,0,0,0);
  236.             }
  237.  
  238.             if (nmt.Source().Empty())
  239.             {
  240.                 nmt.Source().Set( Ram::RAM, true, true, NameTable::SIZE, nameTable.ram );
  241.                 nmt.SwapBanks<SIZE_2K,0x0000>(0,0);
  242.             }
  243.  
  244.             chr.ResetAccessor();
  245.             nmt.ResetAccessors();
  246.  
  247.             cycles.vClock = 0;
  248.             cycles.count = Cpu::CYCLE_MAX;
  249.  
  250.             scanline = SCANLINE_VBLANK;
  251.  
  252.             io.address = 0;
  253.             io.pattern = 0;
  254.             io.line.Unset();
  255.  
  256.             tiles.pattern[0] = 0;
  257.             tiles.pattern[1] = 0;
  258.             tiles.attribute = 0;
  259.             tiles.index = 8;
  260.             tiles.mask = 0;
  261.  
  262.             oam.index = 0;
  263.             oam.address = 0;
  264.             oam.latch = 0;
  265.             oam.spriteZeroInLine = false;
  266.             oam.phase = &Ppu::EvaluateSpritesPhase0;
  267.             oam.buffered = oam.buffer;
  268.             oam.visible = oam.output;
  269.             oam.mask = 0;
  270.  
  271.             output.target = NULL;
  272.  
  273.             hActiveHook.Unset();
  274.             hBlankHook.Unset();
  275.  
  276.             UpdateStates();
  277.  
  278.             screen.Clear();
  279.         }
  280.  
  281.         uint Ppu::SetAddressLineHook(const Core::Io::Line& line)
  282.         {
  283.             io.line = line;
  284.             return io.address;
  285.         }
  286.  
  287.         void Ppu::SetHActiveHook(const Hook& hook)
  288.         {
  289.             hActiveHook = hook;
  290.         }
  291.  
  292.         void Ppu::SetHBlankHook(const Hook& hook)
  293.         {
  294.             hBlankHook = hook;
  295.         }
  296.  
  297.         void Ppu::UpdateStates()
  298.         {
  299.             oam.height = (regs.ctrl[0] >> 2 & 8) + 8;
  300.  
  301.             tiles.show[0] = (regs.ctrl[1] & Regs::CTRL1_BG_ENABLED) ? 0xFF : 0x00;
  302.             tiles.show[1] = (regs.ctrl[1] & Regs::CTRL1_BG_ENABLED_NO_CLIP) == Regs::CTRL1_BG_ENABLED_NO_CLIP ? 0xFF : 0x00;
  303.  
  304.             oam.show[0] = (regs.ctrl[1] & Regs::CTRL1_SP_ENABLED) ? 0xFF : 0x00;
  305.             oam.show[1] = (regs.ctrl[1] & Regs::CTRL1_SP_ENABLED_NO_CLIP) == Regs::CTRL1_SP_ENABLED_NO_CLIP ? 0xFF : 0x00;
  306.  
  307.             UpdatePalette();
  308.         }
  309.  
  310.         void Ppu::UpdatePalette()
  311.         {
  312.             for (uint i=0, c=Coloring(), e=Emphasis(); i < Palette::SIZE; ++i)
  313.                 output.palette[i] = (rgbMap ? rgbMap[palette.ram[i] & uint(Palette::COLOR)] : palette.ram[i]) & c | e;
  314.         }
  315.  
  316.         void Ppu::SaveState(State::Saver& state,const dword baseChunk) const
  317.         {
  318.             state.Begin( baseChunk );
  319.  
  320.             {
  321.                 const byte data[11] =
  322.                 {
  323.                     regs.ctrl[0],
  324.                     regs.ctrl[1],
  325.                     regs.status,
  326.                     scroll.address & 0xFF,
  327.                     scroll.address >> 8,
  328.                     scroll.latch & 0xFF,
  329.                     scroll.latch >> 8,
  330.                     scroll.xFine | scroll.toggle << 3,
  331.                     regs.oam,
  332.                     io.buffer,
  333.                     io.latch
  334.                 };
  335.  
  336.                 state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
  337.             }
  338.  
  339.             state.Begin( AsciiId<'P','A','L'>::V ).Compress( palette.ram   ).End();
  340.             state.Begin( AsciiId<'O','A','M'>::V ).Compress( oam.ram       ).End();
  341.             state.Begin( AsciiId<'N','M','T'>::V ).Compress( nameTable.ram ).End();
  342.  
  343.             if (model == PPU_RP2C02)
  344.                 state.Begin( AsciiId<'F','R','M'>::V ).Write8( (regs.frame & Regs::FRAME_ODD) == 0 ).End();
  345.  
  346.             if (cycles.hClock == HCLOCK_BOOT)
  347.                 state.Begin( AsciiId<'P','O','W'>::V ).Write8( 0x0 ).End();
  348.  
  349.             state.End();
  350.         }
  351.  
  352.         void Ppu::LoadState(State::Loader& state)
  353.         {
  354.             cycles.hClock = HCLOCK_DUMMY;
  355.             regs.frame = 0;
  356.             output.burstPhase = 0;
  357.  
  358.             while (const dword chunk = state.Begin())
  359.             {
  360.                 switch (chunk)
  361.                 {
  362.                     case AsciiId<'R','E','G'>::V:
  363.                     {
  364.                         State::Loader::Data<11> data( state );
  365.  
  366.                         regs.ctrl[0]   = data[0];
  367.                         regs.ctrl[1]   = data[1];
  368.                         regs.status    = data[2] & Regs::STATUS_BITS;
  369.                         scroll.address = data[3] | (data[4] << 8 & 0x7F00);
  370.                         scroll.latch   = data[5] | (data[6] << 8 & 0x7F00);
  371.                         scroll.xFine   = data[7] & 0x7;
  372.                         scroll.toggle  = data[7] >> 3 & 0x1;
  373.                         regs.oam       = data[8];
  374.                         io.buffer      = data[9];
  375.                         io.latch       = data[10];
  376.  
  377.                         break;
  378.                     }
  379.  
  380.                     case AsciiId<'P','A','L'>::V:
  381.  
  382.                         state.Uncompress( palette.ram );
  383.                         break;
  384.  
  385.                     case AsciiId<'O','A','M'>::V:
  386.  
  387.                         state.Uncompress( oam.ram );
  388.                         break;
  389.  
  390.                     case AsciiId<'N','M','T'>::V:
  391.  
  392.                         state.Uncompress( nameTable.ram );
  393.                         break;
  394.  
  395.                     case AsciiId<'F','R','M'>::V:
  396.  
  397.                         if (model == PPU_RP2C02)
  398.                             regs.frame = (state.Read8() & 0x1) ? 0 : Regs::FRAME_ODD;
  399.  
  400.                         break;
  401.  
  402.                     case AsciiId<'P','O','W'>::V:
  403.  
  404.                         cycles.hClock = HCLOCK_BOOT;
  405.                         break;
  406.                 }
  407.  
  408.                 state.End();
  409.             }
  410.  
  411.             UpdateStates();
  412.         }
  413.  
  414.         void Ppu::EnableCpuSynchronization()
  415.         {
  416.             cpu.AddHook( Hook(this,&Ppu::Hook_Sync) );
  417.         }
  418.  
  419.         void Ppu::ChrMem::ResetAccessor()
  420.         {
  421.             accessor.Set( this, &ChrMem::Access_Pattern );
  422.         }
  423.  
  424.         void Ppu::NmtMem::ResetAccessors()
  425.         {
  426.             accessors[0].Set( this, &NmtMem::Access_Name_2000 );
  427.             accessors[1].Set( this, &NmtMem::Access_Name_2400 );
  428.             accessors[2].Set( this, &NmtMem::Access_Name_2800 );
  429.             accessors[3].Set( this, &NmtMem::Access_Name_2C00 );
  430.         }
  431.  
  432.         void Ppu::SetModel(const PpuModel m,const bool yuvConversion)
  433.         {
  434.             if (model != m)
  435.             {
  436.                 model = m;
  437.                 regs.frame = 0;
  438.                 output.burstPhase = 0;
  439.  
  440.                 switch (model)
  441.                 {
  442.                     case PPU_RP2C07: cycles.one = PPU_RP2C07_CC; break;
  443.                     case PPU_DENDY:  cycles.one = PPU_DENDY_CC;  break;
  444.                     default:         cycles.one = PPU_RP2C02_CC; break;
  445.                 }
  446.             }
  447.  
  448.             const byte* const map =
  449.             (
  450.                 model == PPU_RP2C04_0001 ? yuvMaps[0] :
  451.                 model == PPU_RP2C04_0002 ? yuvMaps[1] :
  452.                 model == PPU_RP2C04_0003 ? yuvMaps[2] :
  453.                 model == PPU_RP2C04_0004 ? yuvMaps[3] :
  454.                                            NULL
  455.             );
  456.  
  457.             const byte* const tmp[2] =
  458.             {
  459.                 yuvConversion ? NULL : map,
  460.                 yuvConversion ? map : NULL
  461.             };
  462.  
  463.             if (yuvMap != tmp[0] || rgbMap != tmp[1])
  464.             {
  465.                 yuvMap = tmp[0];
  466.                 rgbMap = tmp[1];
  467.  
  468.                 UpdatePalette();
  469.             }
  470.         }
  471.  
  472.         #ifdef NST_MSVC_OPTIMIZE
  473.         #pragma optimize("", on)
  474.         #endif
  475.  
  476.         NST_FORCE_INLINE Cycle Ppu::GetCycles() const
  477.         {
  478.             return (cycles.vClock + cycles.hClock) * cycles.one;
  479.         }
  480.  
  481.         NST_FORCE_INLINE Cycle Ppu::GetLocalCycles(Cycle clock) const
  482.         {
  483.             NST_COMPILE_ASSERT( PPU_DENDY_CC == PPU_RP2C02_CC || PPU_DENDY_CC == PPU_RP2C07_CC );
  484.             return cycles.one == PPU_RP2C02_CC ? clock / PPU_RP2C02_CC : (clock+PPU_RP2C07_CC-1) / PPU_RP2C07_CC;
  485.         }
  486.  
  487.         void Ppu::BeginFrame(bool frameLock)
  488.         {
  489.             NST_ASSERT
  490.             (
  491.                 (scanline == SCANLINE_VBLANK) &&
  492.                 (cycles.hClock == HCLOCK_BOOT || cycles.hClock == HCLOCK_DUMMY) &&
  493.                 (cpu.GetModel() == CPU_RP2A07) == (model == PPU_RP2C07) &&
  494.                 (cpu.GetModel() == CPU_DENDY)  == (model == PPU_DENDY)
  495.             );
  496.  
  497.             oam.limit = oam.buffer + ((oam.spriteLimit || frameLock) ? Oam::STD_LINE_SPRITES*4 : Oam::MAX_LINE_SPRITES*4);
  498.             output.target = output.pixels;
  499.  
  500.             Cycle frame;
  501.  
  502.             switch (model)
  503.             {
  504.                 case PPU_RP2C02:
  505.  
  506.                     regs.frame ^= Regs::FRAME_ODD;
  507.  
  508.                 default:
  509.  
  510.                     if (cycles.hClock == HCLOCK_DUMMY)
  511.                     {
  512.                         cycles.vClock = PPU_RP2C02_HVINT / PPU_RP2C02_CC - HCLOCK_DUMMY;
  513.                         cycles.count = PPU_RP2C02_HVINT;
  514.                         frame = PPU_RP2C02_HVSYNC_0;
  515.                     }
  516.                     else
  517.                     {
  518.                         cycles.vClock = PPU_RP2C02_HVSYNCBOOT / PPU_RP2C02_CC - HCLOCK_BOOT;
  519.                         cycles.count = PPU_RP2C02_HVSYNCBOOT;
  520.                         frame = PPU_RP2C02_HVSYNCBOOT;
  521.                     }
  522.                     break;
  523.  
  524.                 case PPU_RP2C07:
  525.  
  526.                     if (cycles.hClock == HCLOCK_DUMMY)
  527.                     {
  528.                         cycles.vClock = PPU_RP2C07_HVINT / PPU_RP2C07_CC - HCLOCK_DUMMY;
  529.                         cycles.count = PPU_RP2C07_HVINT;
  530.                         frame = PPU_RP2C07_HVSYNC;
  531.                     }
  532.                     else
  533.                     {
  534.                         cycles.vClock = PPU_RP2C07_HVSYNCBOOT / PPU_RP2C07_CC - HCLOCK_BOOT;
  535.                         cycles.count = PPU_RP2C07_HVSYNCBOOT;
  536.                         frame = PPU_RP2C07_HVSYNCBOOT;
  537.                     }
  538.                     break;
  539.  
  540.                 case PPU_DENDY:
  541.  
  542.                     if (cycles.hClock == HCLOCK_DUMMY)
  543.                     {
  544.                         cycles.vClock = PPU_DENDY_HVINT / PPU_DENDY_CC - HCLOCK_DUMMY;
  545.                         cycles.count = PPU_DENDY_HVINT;
  546.                         frame = PPU_DENDY_HVSYNC;
  547.                     }
  548.                     else
  549.                     {
  550.                         cycles.vClock = PPU_DENDY_HVSYNCBOOT / PPU_DENDY_CC - HCLOCK_BOOT;
  551.                         cycles.count = PPU_DENDY_HVSYNCBOOT;
  552.                         frame = PPU_DENDY_HVSYNCBOOT;
  553.                     }
  554.                     break;
  555.             }
  556.  
  557.             cpu.SetFrameCycles( frame );
  558.         }
  559.  
  560.         NES_HOOK(Ppu,Sync)
  561.         {
  562.             const Cycle elapsed = cpu.GetCycles();
  563.  
  564.             if (cycles.count < elapsed)
  565.             {
  566.                 cycles.count = GetLocalCycles( elapsed ) - cycles.vClock;
  567.                 Run();
  568.             }
  569.         }
  570.  
  571.         void Ppu::EndFrame()
  572.         {
  573.             if (cycles.count != Cpu::CYCLE_MAX)
  574.             {
  575.                 cycles.count = Cpu::CYCLE_MAX;
  576.                 Run();
  577.             }
  578.         }
  579.  
  580.         void Ppu::Update(Cycle dataSetup,const uint readAddress)
  581.         {
  582.             dataSetup += cpu.Update( readAddress );
  583.  
  584.             if (cycles.count < dataSetup)
  585.             {
  586.                 cycles.count = GetLocalCycles( dataSetup ) - cycles.vClock;
  587.                 Run();
  588.             }
  589.         }
  590.  
  591.         void Ppu::SetMirroring(const byte (&banks)[4])
  592.         {
  593.             Update( cycles.one );
  594.  
  595.             NST_ASSERT( banks[0] < 4 && banks[1] < 4 && banks[2] < 4 && banks[3] < 4 );
  596.             nmt.SwapBanks<SIZE_1K,0x0000>( banks[0], banks[1], banks[2], banks[3] );
  597.         }
  598.  
  599.         void Ppu::SetMirroring(NmtMirroring mirroring)
  600.         {
  601.             Update( cycles.one );
  602.  
  603.             nmt.SwapBanks<SIZE_1K,0x0000>
  604.             (
  605.                 uint(mirroring) >> 0 & 0x1U,
  606.                 uint(mirroring) >> 1 & 0x1U,
  607.                 uint(mirroring) >> 2 & 0x1U,
  608.                 uint(mirroring) >> 3 & 0x1U
  609.             );
  610.         }
  611.  
  612.         NES_ACCESSOR(Ppu::ChrMem,Pattern)
  613.         {
  614.             return Peek( address );
  615.         }
  616.  
  617.         NES_ACCESSOR(Ppu::NmtMem,Name_2000)
  618.         {
  619.             return (*this)[0][address];
  620.         }
  621.  
  622.         NES_ACCESSOR(Ppu::NmtMem,Name_2400)
  623.         {
  624.             return (*this)[1][address];
  625.         }
  626.  
  627.         NES_ACCESSOR(Ppu::NmtMem,Name_2800)
  628.         {
  629.             return (*this)[2][address];
  630.         }
  631.  
  632.         NES_ACCESSOR(Ppu::NmtMem,Name_2C00)
  633.         {
  634.             return (*this)[3][address];
  635.         }
  636.  
  637.         NST_FORCE_INLINE uint Ppu::Chr::FetchPattern(uint address) const
  638.         {
  639.             return accessor.Fetch( address & 0x1FFF );
  640.         }
  641.  
  642.         NST_FORCE_INLINE uint Ppu::Nmt::FetchName(uint address) const
  643.         {
  644.             return accessors[address >> 10 & 0x3].Fetch( address & 0x3FF );
  645.         }
  646.  
  647.         NST_FORCE_INLINE uint Ppu::Nmt::FetchAttribute(uint address) const
  648.         {
  649.             return accessors[address >> 10 & 0x3].Fetch( 0x3C0 | (address & 0x03F) );
  650.         }
  651.  
  652.         NST_FORCE_INLINE void Ppu::UpdateAddressLine(uint address)
  653.         {
  654.             NST_ASSERT( address <= 0x3FFF );
  655.             io.address = address;
  656.  
  657.             if (io.line)
  658.                 io.line.Toggle( io.address, GetCycles() );
  659.         }
  660.  
  661.         NST_FORCE_INLINE void Ppu::UpdateVramAddress()
  662.         {
  663.             if ((scanline != SCANLINE_VBLANK ) && (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED))
  664.             {
  665.                 scroll.ClockX();
  666.                 scroll.ClockY();
  667.             }
  668.             else
  669.             {
  670.                 scroll.address = (scroll.address + ((regs.ctrl[0] & Regs::CTRL0_INC32) ? 32 : 1)) & 0x7FFF;
  671.             }
  672.         }
  673.  
  674.         NST_FORCE_INLINE void Ppu::OpenName()
  675.         {
  676.             UpdateAddressLine( 0x2000 | (scroll.address & 0x0FFF) );
  677.         }
  678.  
  679.         NST_FORCE_INLINE void Ppu::FetchName()
  680.         {
  681.             io.pattern = nmt.FetchName( io.address ) << 4 | scroll.address >> 12 | (regs.ctrl[0] << 8 & 0x1000);
  682.         }
  683.  
  684.         NST_FORCE_INLINE void Ppu::OpenAttribute()
  685.         {
  686.             UpdateAddressLine( 0x23C0 | (scroll.address & 0x0C00) | (scroll.address >> 4 & 0x0038) | (scroll.address >> 2 & 0x0007) );
  687.         }
  688.  
  689.         NST_FORCE_INLINE void Ppu::FetchAttribute()
  690.         {
  691.             tiles.attribute = nmt.FetchAttribute( io.address ) >> ((scroll.address & 0x2) | (scroll.address >> 4 & 0x4));
  692.         }
  693.  
  694.         NST_FORCE_INLINE void Ppu::OpenPattern(uint address)
  695.         {
  696.             UpdateAddressLine( address );
  697.         }
  698.  
  699.         NST_FORCE_INLINE uint Ppu::FetchSpPattern() const
  700.         {
  701.             return chr.FetchPattern( io.address );
  702.         }
  703.  
  704.         NST_FORCE_INLINE void Ppu::FetchBgPattern0()
  705.         {
  706.             const uint pattern = chr.FetchPattern( io.address );
  707.  
  708.             tiles.pattern[1] = pattern >> 0 & 0x55;
  709.             tiles.pattern[0] = pattern >> 1 & 0x55;
  710.         }
  711.  
  712.         NST_FORCE_INLINE void Ppu::FetchBgPattern1()
  713.         {
  714.             const uint pattern = chr.FetchPattern( io.address );
  715.  
  716.             tiles.pattern[0] |= pattern << 0 & 0xAA;
  717.             tiles.pattern[1] |= pattern << 1 & 0xAA;
  718.         }
  719.  
  720.         uint Ppu::GetPixelCycles() const
  721.         {
  722.             return (scanline+1)-1U < 240 ? scanline * 256 + NST_MIN(cycles.hClock,255) : ~0U;
  723.         }
  724.  
  725.         NST_FORCE_INLINE bool Ppu::IsDead() const
  726.         {
  727.             return scanline == SCANLINE_VBLANK || !(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED);
  728.         }
  729.  
  730.         NST_FORCE_INLINE uint Ppu::Coloring() const
  731.         {
  732.             return (regs.ctrl[1] & Regs::CTRL1_MONOCHROME) ? Palette::MONO : Palette::COLOR;
  733.         }
  734.  
  735.         NST_FORCE_INLINE uint Ppu::Emphasis() const
  736.         {
  737.             return (regs.ctrl[1] & Regs::CTRL1_EMPHASIS) << 1;
  738.         }
  739.  
  740.         NES_POKE_D(Ppu,2000)
  741.         {
  742.             Update( cycles.one );
  743.  
  744.             NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
  745.  
  746.             if (cpu.GetCycles() >= cycles.reset)
  747.             {
  748.                 scroll.latch = (scroll.latch & 0x73FF) | (data & 0x03) << 10;
  749.                 oam.height = (data >> 2 & 8) + 8;
  750.  
  751.                 io.latch = data;
  752.                 data = regs.ctrl[0] ;
  753.                 regs.ctrl[0] = io.latch;
  754.  
  755.                 if ((regs.ctrl[0] & regs.status & Regs::CTRL0_NMI) > data)
  756.                 {
  757.                     const Cycle clock = cpu.GetCycles() + cycles.one;
  758.  
  759.                     if (clock < GetHVIntClock())
  760.                         cpu.DoNMI( clock );
  761.                 }
  762.             }
  763.         }
  764.  
  765.         NES_POKE_D(Ppu,2001)
  766.         {
  767.             Update( cycles.one );
  768.  
  769.             NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
  770.  
  771.             if (cpu.GetCycles() >= cycles.reset)
  772.             {
  773.                 if ((regs.ctrl[1] ^ data) & (Regs::CTRL1_BG_ENABLED_NO_CLIP|Regs::CTRL1_SP_ENABLED_NO_CLIP))
  774.                 {
  775.                     tiles.show[0] = (data & Regs::CTRL1_BG_ENABLED) ? 0xFF : 0x00;
  776.                     tiles.show[1] = (data & Regs::CTRL1_BG_ENABLED_NO_CLIP) == Regs::CTRL1_BG_ENABLED_NO_CLIP ? 0xFF : 0x00;
  777.  
  778.                     oam.show[0] = (data & Regs::CTRL1_SP_ENABLED) ? 0xFF : 0x00;
  779.                     oam.show[1] = (data & Regs::CTRL1_SP_ENABLED_NO_CLIP) == Regs::CTRL1_SP_ENABLED_NO_CLIP ? 0xFF : 0x00;
  780.  
  781.                     const uint pos = (cycles.hClock - 8) >= (256-16);
  782.  
  783.                     tiles.mask = tiles.show[pos];
  784.                     oam.mask = oam.show[pos];
  785.  
  786.                     if ((regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) && !(data & Regs::CTRL1_BG_SP_ENABLED))
  787.                         UpdateAddressLine(scroll.address & 0x3fff);
  788.                 }
  789.  
  790.                 io.latch = data;
  791.                 data = (regs.ctrl[1] ^ data) & (Regs::CTRL1_EMPHASIS|Regs::CTRL1_MONOCHROME);
  792.                 regs.ctrl[1] = io.latch;
  793.  
  794.                 if (data)
  795.                 {
  796.                     const uint ce[] = { Coloring(), Emphasis() };
  797.  
  798.                     const byte* const NST_RESTRICT map = rgbMap;
  799.  
  800.                     if (!map)
  801.                     {
  802.                         for (uint i=0; i < Palette::SIZE; ++i)
  803.                             output.palette[i] = palette.ram[i] & ce[0] | ce[1];
  804.                     }
  805.                     else
  806.                     {
  807.                         for (uint i=0; i < Palette::SIZE; ++i)
  808.                             output.palette[i] = map[palette.ram[i] & Palette::COLOR] & ce[0] | ce[1];
  809.                     }
  810.                 }
  811.             }
  812.         }
  813.  
  814.         NES_PEEK_A(Ppu,2002)
  815.         {
  816.             Update( cycles.one, address );
  817.  
  818.             uint status = regs.status & 0xFF;
  819.  
  820.             regs.status &= (Regs::STATUS_VBLANK^0xFFU);
  821.             scroll.toggle = 0;
  822.             io.latch = (io.latch & Regs::STATUS_LATCH) | status;
  823.  
  824.             return io.latch;
  825.         }
  826.  
  827.         NES_PEEK_A(Ppu,2002_RC2C05_01_04)
  828.         {
  829.             return NES_DO_PEEK(2002,address) & 0xC0 | 0x1B;
  830.         }
  831.  
  832.         NES_PEEK_A(Ppu,2002_RC2C05_02)
  833.         {
  834.             return NES_DO_PEEK(2002,address) & 0xC0 | 0x3D;
  835.         }
  836.  
  837.         NES_PEEK_A(Ppu,2002_RC2C05_03)
  838.         {
  839.             return NES_DO_PEEK(2002,address) & 0xC0 | 0x1C;
  840.         }
  841.  
  842.         NES_POKE_D(Ppu,2003)
  843.         {
  844.             Update( cycles.one );
  845.  
  846.             regs.oam = data;
  847.             io.latch = data;
  848.         }
  849.  
  850.         NES_POKE_D(Ppu,2004)
  851.         {
  852.             Update( cycles.one );
  853.  
  854.             NST_ASSERT( regs.oam < Oam::SIZE );
  855.             NST_VERIFY( IsDead() );
  856.  
  857.             if (IsDead())
  858.             {
  859.                 if ((regs.oam & 0x03) == 0x02)
  860.                     data &= 0xE3;
  861.             }
  862.             else
  863.             {
  864.                 data = 0xFF;
  865.             }
  866.  
  867.             byte* const NST_RESTRICT value = oam.ram + regs.oam;
  868.             regs.oam = (regs.oam + 1) & 0xFF;
  869.             io.latch = data;
  870.             *value = data;
  871.         }
  872.  
  873.         NES_PEEK(Ppu,2004)
  874.         {
  875.             NST_ASSERT( regs.oam <= 0xFF );
  876.  
  877.             if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() - (cpu.GetFrameCycles() - (341 * 241) * cycles.one) >= (341 * 240) * cycles.one)
  878.             {
  879.                 io.latch = oam.ram[regs.oam];
  880.             }
  881.             else
  882.             {
  883.                 Update( cycles.one );
  884.  
  885.                 io.latch = oam.latch;
  886.             }
  887.  
  888.             return io.latch;
  889.         }
  890.  
  891.         NES_POKE_D(Ppu,2005)
  892.         {
  893.             Update( cycles.one );
  894.  
  895.             NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
  896.  
  897.             if (cpu.GetCycles() >= cycles.reset)
  898.             {
  899.                 io.latch = data;
  900.  
  901.                 if (scroll.toggle ^= 1)
  902.                 {
  903.                     scroll.latch = (scroll.latch & 0x7FE0) | (data >> 3);
  904.                     scroll.xFine = data & 0x7;
  905.                 }
  906.                 else
  907.                 {
  908.                     scroll.latch = (scroll.latch & 0x0C1F) | ((data << 2 | data << 12) & 0x73E0);
  909.                 }
  910.             }
  911.         }
  912.  
  913.         NES_POKE_D(Ppu,2006)
  914.         {
  915.             Update( cycles.one );
  916.  
  917.             NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
  918.  
  919.             if (cpu.GetCycles() >= cycles.reset)
  920.             {
  921.                 io.latch = data;
  922.  
  923.                 if (scroll.toggle ^= 1)
  924.                 {
  925.                     scroll.latch = (scroll.latch & 0x00FF) | (data & 0x3F) << 8;
  926.                 }
  927.                 else
  928.                 {
  929.                     scroll.latch = (scroll.latch & 0x7F00) | data;
  930.                     scroll.address = scroll.latch;
  931.                     if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
  932.                         (scanline == SCANLINE_VBLANK)) {
  933.                         UpdateAddressLine(scroll.address & 0x3fff);
  934.                     }
  935.                 }
  936.             }
  937.         }
  938.  
  939.         NES_POKE_D(Ppu,2007)
  940.         {
  941.             Update( cycles.one * 4 );
  942.  
  943.             uint address = scroll.address;
  944.  
  945.             UpdateVramAddress();
  946.             if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
  947.                 (scanline == SCANLINE_VBLANK)) {
  948.                 UpdateAddressLine(scroll.address & 0x3fff);
  949.             }
  950.             else {
  951.                 return;
  952.             }
  953.  
  954.             io.latch = data;
  955.  
  956.             if ((address & 0x3F00) == 0x3F00)
  957.             {
  958.                 address &= 0x1F;
  959.  
  960.                 const uint final = (!rgbMap ? data : rgbMap[data & Palette::COLOR]) & Coloring() | Emphasis();
  961.  
  962.                 palette.ram[address] = data;
  963.                 output.palette[address] = final;
  964.  
  965.                 if (!(address & 0x3))
  966.                 {
  967.                     palette.ram[address ^ 0x10] = data;
  968.                     output.palette[address ^ 0x10] = final;
  969.                 }
  970.                
  971.                 output.bgColor = palette.ram[0] & uint(Palette::COLOR);
  972.             }
  973.             else
  974.             {
  975.                 address &= 0x3FFF;
  976.  
  977.                 if (address >= 0x2000)
  978.                     nmt.Poke( address & 0xFFF, data );
  979.                 else
  980.                     chr.Poke( address, data );
  981.             }
  982.         }
  983.  
  984.         NES_PEEK_A(Ppu,2007)
  985.         {
  986.             Update( cycles.one, address );
  987.  
  988.             address = scroll.address & 0x3FFF;
  989.             UpdateVramAddress();
  990.             if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
  991.                 (scanline == SCANLINE_VBLANK)) {
  992.                 UpdateAddressLine(scroll.address & 0x3fff);
  993.             }
  994.  
  995.             io.latch = (address & 0x3F00) != 0x3F00 ? io.buffer : palette.ram[address & 0x1F] & Coloring();
  996.             io.buffer = (address >= 0x2000 ? nmt.FetchName( address ) : chr.FetchPattern( address ));
  997.  
  998.             return io.latch;
  999.         }
  1000.  
  1001.         NES_POKE_D(Ppu,2xxx)
  1002.         {
  1003.             io.latch = data;
  1004.         }
  1005.  
  1006.         NES_PEEK(Ppu,2xxx)
  1007.         {
  1008.             return io.latch;
  1009.         }
  1010.  
  1011.         NES_PEEK(Ppu,3000)
  1012.         {
  1013.             Update( cycles.one );
  1014.  
  1015.             return io.latch;
  1016.         }
  1017.  
  1018.         NES_POKE_D(Ppu,4014)
  1019.         {
  1020.             if (cpu.IsOddCycle())
  1021.                 cpu.StealCycles( cpu.GetClock() );
  1022.  
  1023.             Update( cycles.one );
  1024.             cpu.StealCycles( cpu.GetClock() );
  1025.  
  1026.             NST_ASSERT( regs.oam < 0x100 );
  1027.  
  1028.             data <<= 8;
  1029.  
  1030.             if ((regs.oam == 0x00 && data < 0x2000) && (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() <= GetHVIntClock() - cpu.GetClock() * 512))
  1031.             {
  1032.                 cpu.StealCycles( cpu.GetClock() * 512 );
  1033.  
  1034.                 const byte* const NST_RESTRICT cpuRam = cpu.GetRam() + (data & (Cpu::RAM_SIZE-1));
  1035.                 byte* const NST_RESTRICT oamRam = oam.ram;
  1036.  
  1037.                 for (uint i=0x00; i < 0x100; i += 0x4)
  1038.                 {
  1039.                     oamRam[i+0x0] = cpuRam[i+0x0];
  1040.                     oamRam[i+0x1] = cpuRam[i+0x1];
  1041.                     oamRam[i+0x2] = cpuRam[i+0x2] & 0xE3U;
  1042.                     oamRam[i+0x3] = cpuRam[i+0x3];
  1043.                 }
  1044.  
  1045.                 io.latch = oamRam[0xFF];
  1046.             }
  1047.             else do
  1048.             {
  1049.                 io.latch = cpu.Peek( data++ );
  1050.                 cpu.StealCycles( cpu.GetClock() );
  1051.  
  1052.                 Update( cycles.one );
  1053.                 cpu.StealCycles( cpu.GetClock() );
  1054.  
  1055.                 NST_VERIFY( IsDead() );
  1056.  
  1057.                 if (IsDead())
  1058.                 {
  1059.                     if ((regs.oam & 0x03) == 0x02)
  1060.                         io.latch &= 0xE3;
  1061.                 }
  1062.                 else
  1063.                 {
  1064.                     io.latch = 0xFF;
  1065.                 }
  1066.  
  1067.                 byte* const NST_RESTRICT out = oam.ram + regs.oam;
  1068.                 regs.oam = (regs.oam + 1) & 0xFF;
  1069.                 *out = io.latch;
  1070.             }
  1071.             while (data & 0xFF);
  1072.         }
  1073.  
  1074.         NES_PEEK(Ppu,4014)
  1075.         {
  1076.             return 0x40;
  1077.         }
  1078.  
  1079.         NST_FORCE_INLINE void Ppu::Scroll::ClockX()
  1080.         {
  1081.             if ((address & X_TILE) != X_TILE)
  1082.                 address++;
  1083.             else
  1084.                 address ^= (X_TILE|NAME_LOW);
  1085.         }
  1086.  
  1087.         NST_SINGLE_CALL void Ppu::Scroll::ResetX()
  1088.         {
  1089.             address = (address & ((X_TILE|NAME_LOW) ^ 0x7FFFU)) | (latch & (X_TILE|NAME_LOW));
  1090.         }
  1091.  
  1092.         NST_SINGLE_CALL void Ppu::Scroll::ClockY()
  1093.         {
  1094.             if ((address & Y_FINE) != (7U << 12))
  1095.             {
  1096.                 address += (1U << 12);
  1097.             }
  1098.             else switch (address & Y_TILE)
  1099.             {
  1100.                 default:         address = (address & (Y_FINE ^ 0x7FFFU)) + (1U << 5); break;
  1101.                 case (29U << 5): address ^= NAME_HIGH;
  1102.                 case (31U << 5): address &= (Y_FINE|Y_TILE) ^ 0x7FFFU; break;
  1103.             }
  1104.         }
  1105.  
  1106.         NST_SINGLE_CALL void Ppu::PreLoadTiles()
  1107.         {
  1108.             const byte* const NST_RESTRICT src[] =
  1109.             {
  1110.                 tileLut.block[tiles.pattern[0] | (tiles.attribute & 0x3U) << 8],
  1111.                 tileLut.block[tiles.pattern[1] | (tiles.attribute & 0x3U) << 8]
  1112.             };
  1113.  
  1114.             NST_ASSERT( tiles.index == 8 );
  1115.  
  1116.             byte* const NST_RESTRICT dst = tiles.pixels;
  1117.  
  1118.             dst[0] = src[0][0];
  1119.             dst[1] = src[1][0];
  1120.             dst[2] = src[0][1];
  1121.             dst[3] = src[1][1];
  1122.             dst[4] = src[0][2];
  1123.             dst[5] = src[1][2];
  1124.             dst[6] = src[0][3];
  1125.             dst[7] = src[1][3];
  1126.         }
  1127.  
  1128.         NST_SINGLE_CALL void Ppu::LoadTiles()
  1129.         {
  1130.             const byte* const NST_RESTRICT src[] =
  1131.             {
  1132.                 tileLut.block[tiles.pattern[0] | (tiles.attribute & 0x3U) << 8],
  1133.                 tileLut.block[tiles.pattern[1] | (tiles.attribute & 0x3U) << 8]
  1134.             };
  1135.  
  1136.             NST_ASSERT( tiles.index == 0 || tiles.index == 8 );
  1137.  
  1138.             byte* const NST_RESTRICT dst = tiles.pixels + tiles.index;
  1139.             tiles.index ^= 8U;
  1140.  
  1141.             dst[0] = src[0][0];
  1142.             dst[1] = src[1][0];
  1143.             dst[2] = src[0][1];
  1144.             dst[3] = src[1][1];
  1145.             dst[4] = src[0][2];
  1146.             dst[5] = src[1][2];
  1147.             dst[6] = src[0][3];
  1148.             dst[7] = src[1][3];
  1149.         }
  1150.  
  1151.         NST_FORCE_INLINE void Ppu::EvaluateSpritesEven()
  1152.         {
  1153.             if (cycles.hClock >= 64)
  1154.                 oam.latch = oam.ram[oam.address];
  1155.         }
  1156.  
  1157.         NST_FORCE_INLINE void Ppu::EvaluateSpritesOdd()
  1158.         {
  1159.             (*this.*oam.phase)();
  1160.         }
  1161.  
  1162.         void Ppu::EvaluateSpritesPhase0()
  1163.         {
  1164.         }
  1165.  
  1166.         void Ppu::EvaluateSpritesPhase1()
  1167.         {
  1168.             oam.index++;
  1169.  
  1170.             if (scanline - oam.latch >= oam.height)
  1171.             {
  1172.                 if (oam.index != 64)
  1173.                 {
  1174.                     oam.address = (oam.index != 2 ? oam.address + 4 : 8);
  1175.                 }
  1176.                 else
  1177.                 {
  1178.                     oam.address = 0;
  1179.                     oam.phase = &Ppu::EvaluateSpritesPhase9;
  1180.                 }
  1181.             }
  1182.             else
  1183.             {
  1184.                 oam.address++;
  1185.                 oam.phase = &Ppu::EvaluateSpritesPhase2;
  1186.                 oam.buffered[0] = oam.latch;
  1187.             }
  1188.         }
  1189.  
  1190.         void Ppu::EvaluateSpritesPhase2()
  1191.         {
  1192.             oam.address++;
  1193.             oam.phase = &Ppu::EvaluateSpritesPhase3;
  1194.             oam.buffered[1] = oam.latch;
  1195.         }
  1196.  
  1197.         void Ppu::EvaluateSpritesPhase3()
  1198.         {
  1199.             oam.address++;
  1200.             oam.phase = &Ppu::EvaluateSpritesPhase4;
  1201.             oam.buffered[2] = oam.latch;
  1202.         }
  1203.  
  1204.         void Ppu::EvaluateSpritesPhase4()
  1205.         {
  1206.             oam.buffered[3] = oam.latch;
  1207.             oam.buffered += 4;
  1208.  
  1209.             if (oam.index != 64)
  1210.             {
  1211.                 oam.phase = (oam.buffered != oam.limit ? &Ppu::EvaluateSpritesPhase1 : &Ppu::EvaluateSpritesPhase5);
  1212.  
  1213.                 if (oam.index != 2)
  1214.                 {
  1215.                     oam.address++;
  1216.  
  1217.                     if (oam.index == 1)
  1218.                         oam.spriteZeroInLine = true;
  1219.                 }
  1220.                 else
  1221.                 {
  1222.                     oam.address = 8;
  1223.                 }
  1224.             }
  1225.             else
  1226.             {
  1227.                 oam.address = 0;
  1228.                 oam.phase = &Ppu::EvaluateSpritesPhase9;
  1229.             }
  1230.         }
  1231.  
  1232.         void Ppu::EvaluateSpritesPhase5()
  1233.         {
  1234.             if (scanline - oam.latch >= oam.height)
  1235.             {
  1236.                 oam.address = ((oam.address + 4) & 0xFC) + ((oam.address + 1) & 0x03);
  1237.  
  1238.                 if (oam.address <= 5)
  1239.                 {
  1240.                     oam.phase = &Ppu::EvaluateSpritesPhase9;
  1241.                     oam.address &= 0xFC;
  1242.                 }
  1243.             }
  1244.             else
  1245.             {
  1246.                 oam.phase = &Ppu::EvaluateSpritesPhase6;
  1247.                 oam.address = (oam.address + 1) & 0xFF;
  1248.                 regs.status |= Regs::STATUS_SP_OVERFLOW;
  1249.             }
  1250.         }
  1251.  
  1252.         void Ppu::EvaluateSpritesPhase6()
  1253.         {
  1254.             oam.phase = &Ppu::EvaluateSpritesPhase7;
  1255.             oam.address = (oam.address + 1) & 0xFF;
  1256.         }
  1257.  
  1258.         void Ppu::EvaluateSpritesPhase7()
  1259.         {
  1260.             oam.phase = &Ppu::EvaluateSpritesPhase8;
  1261.             oam.address = (oam.address + 1) & 0xFF;
  1262.         }
  1263.  
  1264.         void Ppu::EvaluateSpritesPhase8()
  1265.         {
  1266.             oam.phase = &Ppu::EvaluateSpritesPhase9;
  1267.             oam.address = (oam.address + 1) & 0xFF;
  1268.  
  1269.             if ((oam.address & 0x3) == 0x3)
  1270.                 oam.address++;
  1271.  
  1272.             oam.address &= 0xFC;
  1273.         }
  1274.  
  1275.         void Ppu::EvaluateSpritesPhase9()
  1276.         {
  1277.             oam.address = (oam.address + 4) & 0xFF;
  1278.         }
  1279.  
  1280.         NST_FORCE_INLINE uint Ppu::OpenSprite() const
  1281.         {
  1282.             return (regs.ctrl[0] & (Regs::CTRL0_SP_OFFSET|Regs::CTRL0_SP8X16)) ? 0x1FF0 : 0x0FF0;
  1283.         }
  1284.  
  1285.         NST_FORCE_INLINE uint Ppu::OpenSprite(const byte* const NST_RESTRICT buffer) const
  1286.         {
  1287.             uint address;
  1288.             const uint comparitor = (uint(scanline) - buffer[0]) ^ ((buffer[2] & uint(Oam::Y_FLIP)) ? 0xF : 0x0);
  1289.  
  1290.             if (regs.ctrl[0] & Regs::CTRL0_SP8X16)
  1291.             {
  1292.                 address =
  1293.                 (
  1294.                     ((buffer[1] & uint(Oam::TILE_LSB)) << 12) |
  1295.                     ((buffer[1] & (Oam::TILE_LSB ^ 0xFFU)) << 4) |
  1296.                     ((comparitor & Oam::RANGE_MSB) << 1)
  1297.                 );
  1298.             }
  1299.             else
  1300.             {
  1301.                 address = (regs.ctrl[0] & Regs::CTRL0_SP_OFFSET) << 9 | buffer[1] << 4;
  1302.             }
  1303.  
  1304.             return address | comparitor & Oam::XFINE;
  1305.         }
  1306.  
  1307.         NST_FORCE_INLINE void Ppu::LoadSprite(const uint pattern0,const uint pattern1,const byte* const NST_RESTRICT buffer)
  1308.         {
  1309.             if (pattern0 | pattern1)
  1310.             {
  1311.                 uint a = (buffer[2] & uint(Oam::X_FLIP)) ? 7 : 0;
  1312.  
  1313.                 uint p =
  1314.                 (
  1315.                     (pattern0 >> 1 & 0x0055) | (pattern1 << 0 & 0x00AA) |
  1316.                     (pattern0 << 8 & 0x5500) | (pattern1 << 9 & 0xAA00)
  1317.                 );
  1318.  
  1319.                 Oam::Output* const NST_RESTRICT entry = oam.visible++;
  1320.  
  1321.                 entry->pixels[( a^=6 )] = ( p       ) & 0x3;
  1322.                 entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
  1323.                 entry->pixels[( a^=6 )] = ( p >>= 2 ) & 0x3;
  1324.                 entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
  1325.                 entry->pixels[( a^=7 )] = ( p >>= 2 ) & 0x3;
  1326.                 entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
  1327.                 entry->pixels[( a^=6 )] = ( p >>= 2 ) & 0x3;
  1328.                 entry->pixels[( a^=2 )] = ( p >>= 2 );
  1329.  
  1330.                 const uint attribute = buffer[2];
  1331.  
  1332.                 entry->x       = buffer[3];
  1333.                 entry->palette = Palette::SPRITE_OFFSET + ((attribute & Oam::COLOR) << 2);
  1334.                 entry->behind  = (attribute & Oam::BEHIND) ? 0x3 : 0x0;
  1335.                 entry->zero    = (buffer == oam.buffer && oam.spriteZeroInLine) ? 0x3 : 0x0;
  1336.             }
  1337.         }
  1338.  
  1339.         void Ppu::LoadExtendedSprites()
  1340.         {
  1341.             const byte* NST_RESTRICT buffer = oam.buffer + (8*4);
  1342.             NST_ASSERT( buffer < oam.buffered );
  1343.  
  1344.             do
  1345.             {
  1346.                 const uint address = OpenSprite( buffer );
  1347.  
  1348.                 const uint patterns[2] =
  1349.                 {
  1350.                     chr.FetchPattern( address | 0x0 ),
  1351.                     chr.FetchPattern( address | 0x8 )
  1352.                 };
  1353.  
  1354.                 LoadSprite( patterns[0], patterns[1], buffer );
  1355.                 buffer += 4;
  1356.             }
  1357.             while (buffer != oam.buffered);
  1358.         }
  1359.  
  1360.         NST_FORCE_INLINE void Ppu::RenderPixel()
  1361.         {
  1362.             uint clock;
  1363.             uint pixel = tiles.pixels[((clock=cycles.hClock++) + scroll.xFine) & 15] & tiles.mask;
  1364.  
  1365.             for (const Oam::Output* NST_RESTRICT sprite=oam.output, *const end=oam.visible; sprite != end; ++sprite)
  1366.             {
  1367.                 uint x = clock - sprite->x;
  1368.  
  1369.                 if (x > 7)
  1370.                     continue;
  1371.  
  1372.                 x = sprite->pixels[x] & oam.mask;
  1373.  
  1374.                 if (x)
  1375.                 {
  1376.                     if (pixel & sprite->zero)
  1377.                         regs.status |= Regs::STATUS_SP_ZERO_HIT;
  1378.  
  1379.                     if (!(pixel & sprite->behind))
  1380.                         pixel = sprite->palette + x;
  1381.  
  1382.                     break;
  1383.                 }
  1384.             }
  1385.  
  1386.             Video::Screen::Pixel* const NST_RESTRICT target = output.target++;
  1387.             *target = output.palette[pixel];
  1388.         }
  1389.  
  1390.         NST_SINGLE_CALL void Ppu::RenderPixel255()
  1391.         {
  1392.             cycles.hClock = 256;
  1393.             uint pixel = tiles.pixels[(255 + scroll.xFine) & 15] & tiles.mask;
  1394.  
  1395.             for (const Oam::Output* NST_RESTRICT sprite=oam.output, *const end=oam.visible; sprite != end; ++sprite)
  1396.             {
  1397.                 uint x = 255U - sprite->x;
  1398.  
  1399.                 if (x > 7)
  1400.                     continue;
  1401.  
  1402.                 x = sprite->pixels[x] & oam.mask;
  1403.  
  1404.                 if (x)
  1405.                 {
  1406.                     if (!(pixel & sprite->behind))
  1407.                         pixel = sprite->palette + x;
  1408.  
  1409.                     break;
  1410.                 }
  1411.             }
  1412.  
  1413.             Video::Screen::Pixel* const NST_RESTRICT target = output.target++;
  1414.             *target = output.palette[pixel];
  1415.         }
  1416.  
  1417.         NST_NO_INLINE void Ppu::Run()
  1418.         {
  1419.             NST_VERIFY( cycles.count != cycles.hClock );
  1420.  
  1421.             if (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED)
  1422.             {
  1423.                 switch (cycles.hClock)
  1424.                 {
  1425.                     case 0:
  1426.                     case 8:
  1427.                     case 16:
  1428.                     case 24:
  1429.                     case 32:
  1430.                     case 40:
  1431.                     case 48:
  1432.                     case 56:
  1433.                     case 72:
  1434.                     case 80:
  1435.                     case 88:
  1436.                     case 96:
  1437.                     case 104:
  1438.                     case 112:
  1439.                     case 120:
  1440.                     case 128:
  1441.                     case 136:
  1442.                     case 144:
  1443.                     case 152:
  1444.                     case 160:
  1445.                     case 168:
  1446.                     case 176:
  1447.                     case 184:
  1448.                     case 192:
  1449.                     case 200:
  1450.                     case 208:
  1451.                     case 216:
  1452.                     case 224:
  1453.                     case 232:
  1454.                     case 240:
  1455.                     case 248:
  1456.                     HActive:
  1457.  
  1458.                         LoadTiles();
  1459.                         EvaluateSpritesEven();
  1460.                         OpenName();
  1461.                         RenderPixel();
  1462.  
  1463.                         if (cycles.count <= cycles.hClock)
  1464.                             break;
  1465.  
  1466.                     case 1:
  1467.                     case 9:
  1468.                     case 17:
  1469.                     case 25:
  1470.                     case 33:
  1471.                     case 41:
  1472.                     case 49:
  1473.                     case 57:
  1474.                     case 65:
  1475.                     case 73:
  1476.                     case 81:
  1477.                     case 89:
  1478.                     case 97:
  1479.                     case 105:
  1480.                     case 113:
  1481.                     case 121:
  1482.                     case 129:
  1483.                     case 137:
  1484.                     case 145:
  1485.                     case 153:
  1486.                     case 161:
  1487.                     case 169:
  1488.                     case 177:
  1489.                     case 185:
  1490.                     case 193:
  1491.                     case 201:
  1492.                     case 209:
  1493.                     case 217:
  1494.                     case 225:
  1495.                     case 233:
  1496.                     case 241:
  1497.                     case 249:
  1498.  
  1499.                         FetchName();
  1500.                         EvaluateSpritesOdd();
  1501.                         RenderPixel();
  1502.  
  1503.                         if (cycles.count <= cycles.hClock)
  1504.                             break;
  1505.  
  1506.                     case 2:
  1507.                     case 10:
  1508.                     case 18:
  1509.                     case 26:
  1510.                     case 34:
  1511.                     case 42:
  1512.                     case 50:
  1513.                     case 58:
  1514.                     case 66:
  1515.                     case 74:
  1516.                     case 82:
  1517.                     case 90:
  1518.                     case 98:
  1519.                     case 106:
  1520.                     case 114:
  1521.                     case 122:
  1522.                     case 130:
  1523.                     case 138:
  1524.                     case 146:
  1525.                     case 154:
  1526.                     case 162:
  1527.                     case 170:
  1528.                     case 178:
  1529.                     case 186:
  1530.                     case 194:
  1531.                     case 202:
  1532.                     case 210:
  1533.                     case 218:
  1534.                     case 226:
  1535.                     case 234:
  1536.                     case 242:
  1537.                     case 250:
  1538.  
  1539.                         EvaluateSpritesEven();
  1540.                         OpenAttribute();
  1541.                         RenderPixel();
  1542.  
  1543.                         if (cycles.count <= cycles.hClock)
  1544.                             break;
  1545.  
  1546.                     case 3:
  1547.                     case 11:
  1548.                     case 19:
  1549.                     case 27:
  1550.                     case 35:
  1551.                     case 43:
  1552.                     case 51:
  1553.                     case 59:
  1554.                     case 67:
  1555.                     case 75:
  1556.                     case 83:
  1557.                     case 91:
  1558.                     case 99:
  1559.                     case 107:
  1560.                     case 115:
  1561.                     case 123:
  1562.                     case 131:
  1563.                     case 139:
  1564.                     case 147:
  1565.                     case 155:
  1566.                     case 163:
  1567.                     case 171:
  1568.                     case 179:
  1569.                     case 187:
  1570.                     case 195:
  1571.                     case 203:
  1572.                     case 211:
  1573.                     case 219:
  1574.                     case 227:
  1575.                     case 235:
  1576.                     case 243:
  1577.                     case 251:
  1578.  
  1579.                         FetchAttribute();
  1580.                         EvaluateSpritesOdd();
  1581.  
  1582.                         if (cycles.hClock == 251)
  1583.                             scroll.ClockY();
  1584.  
  1585.                         scroll.ClockX();
  1586.                         RenderPixel();
  1587.  
  1588.                         if (cycles.count <= cycles.hClock)
  1589.                             break;
  1590.  
  1591.                     case 4:
  1592.                     case 12:
  1593.                     case 20:
  1594.                     case 28:
  1595.                     case 36:
  1596.                     case 44:
  1597.                     case 52:
  1598.                     case 60:
  1599.                     case 68:
  1600.                     case 76:
  1601.                     case 84:
  1602.                     case 92:
  1603.                     case 100:
  1604.                     case 108:
  1605.                     case 116:
  1606.                     case 124:
  1607.                     case 132:
  1608.                     case 140:
  1609.                     case 148:
  1610.                     case 156:
  1611.                     case 164:
  1612.                     case 172:
  1613.                     case 180:
  1614.                     case 188:
  1615.                     case 196:
  1616.                     case 204:
  1617.                     case 212:
  1618.                     case 220:
  1619.                     case 228:
  1620.                     case 236:
  1621.                     case 244:
  1622.                     case 252:
  1623.  
  1624.                         EvaluateSpritesEven();
  1625.                         OpenPattern( io.pattern | 0x0 );
  1626.                         RenderPixel();
  1627.  
  1628.                         if (cycles.count <= cycles.hClock)
  1629.                             break;
  1630.  
  1631.                     case 5:
  1632.                     case 13:
  1633.                     case 21:
  1634.                     case 29:
  1635.                     case 37:
  1636.                     case 45:
  1637.                     case 53:
  1638.                     case 61:
  1639.                     case 69:
  1640.                     case 77:
  1641.                     case 85:
  1642.                     case 93:
  1643.                     case 101:
  1644.                     case 109:
  1645.                     case 117:
  1646.                     case 125:
  1647.                     case 133:
  1648.                     case 141:
  1649.                     case 149:
  1650.                     case 157:
  1651.                     case 165:
  1652.                     case 173:
  1653.                     case 181:
  1654.                     case 189:
  1655.                     case 197:
  1656.                     case 205:
  1657.                     case 213:
  1658.                     case 221:
  1659.                     case 229:
  1660.                     case 237:
  1661.                     case 245:
  1662.                     case 253:
  1663.  
  1664.                         FetchBgPattern0();
  1665.                         EvaluateSpritesOdd();
  1666.                         RenderPixel();
  1667.  
  1668.                         if (cycles.count <= cycles.hClock)
  1669.                             break;
  1670.  
  1671.                     case 6:
  1672.                     case 14:
  1673.                     case 22:
  1674.                     case 30:
  1675.                     case 38:
  1676.                     case 46:
  1677.                     case 54:
  1678.                     case 62:
  1679.                     case 70:
  1680.                     case 78:
  1681.                     case 86:
  1682.                     case 94:
  1683.                     case 102:
  1684.                     case 110:
  1685.                     case 118:
  1686.                     case 126:
  1687.                     case 134:
  1688.                     case 142:
  1689.                     case 150:
  1690.                     case 158:
  1691.                     case 166:
  1692.                     case 174:
  1693.                     case 182:
  1694.                     case 190:
  1695.                     case 198:
  1696.                     case 206:
  1697.                     case 214:
  1698.                     case 222:
  1699.                     case 230:
  1700.                     case 238:
  1701.                     case 246:
  1702.                     case 254:
  1703.  
  1704.                         EvaluateSpritesEven();
  1705.                         OpenPattern( io.pattern | 0x8 );
  1706.                         RenderPixel();
  1707.  
  1708.                         if (cycles.count <= cycles.hClock)
  1709.                             break;
  1710.  
  1711.                         if (cycles.hClock == 255)
  1712.                             goto HActive255;
  1713.  
  1714.                     case 7:
  1715.                     case 15:
  1716.                     case 23:
  1717.                     case 31:
  1718.                     case 39:
  1719.                     case 47:
  1720.                     case 55:
  1721.                     case 63:
  1722.                     case 71:
  1723.                     case 79:
  1724.                     case 87:
  1725.                     case 95:
  1726.                     case 103:
  1727.                     case 111:
  1728.                     case 119:
  1729.                     case 127:
  1730.                     case 135:
  1731.                     case 143:
  1732.                     case 151:
  1733.                     case 159:
  1734.                     case 167:
  1735.                     case 175:
  1736.                     case 183:
  1737.                     case 191:
  1738.                     case 199:
  1739.                     case 207:
  1740.                     case 215:
  1741.                     case 223:
  1742.                     case 231:
  1743.                     case 239:
  1744.                     case 247:
  1745.  
  1746.                         FetchBgPattern1();
  1747.                         EvaluateSpritesOdd();
  1748.                         RenderPixel();
  1749.                         tiles.mask = tiles.show[0];
  1750.                         oam.mask = oam.show[0];
  1751.  
  1752.                         if (cycles.count <= cycles.hClock)
  1753.                             break;
  1754.  
  1755.                         if (cycles.hClock != 64)
  1756.                             goto HActive;
  1757.  
  1758.                     case 64:
  1759.  
  1760.                         NST_VERIFY( regs.oam == 0 );
  1761.                         oam.address = regs.oam & Oam::OFFSET_TO_0_1;
  1762.                         oam.phase = &Ppu::EvaluateSpritesPhase1;
  1763.                         oam.latch = 0xFF;
  1764.                         goto HActive;
  1765.  
  1766.                     case 255:
  1767.                     HActive255:
  1768.  
  1769.                         FetchBgPattern1();
  1770.                         EvaluateSpritesOdd();
  1771.                         RenderPixel255();
  1772.  
  1773.                         if (cycles.count <= 256)
  1774.                             break;
  1775.  
  1776.                     case 256:
  1777.  
  1778.                         OpenName();
  1779.                         oam.latch = 0xFF;
  1780.                         cycles.hClock = 257;
  1781.  
  1782.                         if (cycles.count <= 257)
  1783.                             break;
  1784.  
  1785.                     case 257:
  1786.  
  1787.                         if (hBlankHook)
  1788.                             hBlankHook.Execute();
  1789.  
  1790.                         scroll.ResetX();
  1791.                         oam.visible = oam.output;
  1792.                         cycles.hClock = 258;
  1793.  
  1794.                         if (cycles.count <= 258)
  1795.                             break;
  1796.  
  1797.                     case 258:
  1798.                     case 266:
  1799.                     case 274:
  1800.                     case 282:
  1801.                     case 290:
  1802.                     case 298:
  1803.                     case 306:
  1804.                     case 314:
  1805.                     HBlankSp:
  1806.  
  1807.                         OpenName();
  1808.                         cycles.hClock += 2;
  1809.  
  1810.                         if (cycles.count <= cycles.hClock)
  1811.                             break;
  1812.  
  1813.                     case 260:
  1814.                     case 268:
  1815.                     case 276:
  1816.                     case 284:
  1817.                     case 292:
  1818.                     case 300:
  1819.                     case 308:
  1820.                     case 316:
  1821.                     {
  1822.                         const byte* const buffer = oam.buffer + ((cycles.hClock - 260) / 2);
  1823.                         OpenPattern( buffer >= oam.buffered ? OpenSprite() : OpenSprite(buffer) );
  1824.  
  1825.                         if (scanline == 238 && cycles.hClock == 316)
  1826.                             regs.oam = 0;
  1827.  
  1828.                         if (cycles.count <= ++cycles.hClock)
  1829.                             break;
  1830.                     }
  1831.  
  1832.                     case 261:
  1833.                     case 269:
  1834.                     case 277:
  1835.                     case 285:
  1836.                     case 293:
  1837.                     case 301:
  1838.                     case 309:
  1839.                     case 317:
  1840.  
  1841.                         if (oam.buffer + ((cycles.hClock - 261) / 2) < oam.buffered)
  1842.                             io.pattern = FetchSpPattern();
  1843.  
  1844.                         if (cycles.count <= ++cycles.hClock)
  1845.                             break;
  1846.  
  1847.                     case 262:
  1848.                     case 270:
  1849.                     case 278:
  1850.                     case 286:
  1851.                     case 294:
  1852.                     case 302:
  1853.                     case 310:
  1854.                     case 318:
  1855.  
  1856.                         OpenPattern( io.address | 0x8 );
  1857.  
  1858.                         if (cycles.count <= ++cycles.hClock)
  1859.                             break;
  1860.  
  1861.                     case 263:
  1862.                     case 271:
  1863.                     case 279:
  1864.                     case 287:
  1865.                     case 295:
  1866.                     case 303:
  1867.                     case 311:
  1868.                     case 319:
  1869.                     {
  1870.                         const byte* const buffer = oam.buffer + ((cycles.hClock - 263) / 2);
  1871.  
  1872.                         if (buffer < oam.buffered)
  1873.                             LoadSprite( io.pattern, FetchSpPattern(), buffer );
  1874.  
  1875.                         if (cycles.count <= ++cycles.hClock)
  1876.                             break;
  1877.  
  1878.                         if (cycles.hClock == 320)
  1879.                             goto HBlankBg;
  1880.                     }
  1881.  
  1882.                     case 264:
  1883.                     case 272:
  1884.                     case 280:
  1885.                     case 288:
  1886.                     case 296:
  1887.                     case 304:
  1888.                     case 312:
  1889.  
  1890.                         OpenName();
  1891.                         cycles.hClock += 2;
  1892.  
  1893.                         if (cycles.count <= cycles.hClock)
  1894.                             break;
  1895.  
  1896.                         goto HBlankSp;
  1897.  
  1898.                     case 320:
  1899.                     HBlankBg:
  1900.  
  1901.                         if (oam.buffer + (8*4) < oam.buffered)
  1902.                             LoadExtendedSprites();
  1903.  
  1904.                         OpenName();
  1905.  
  1906.                         if (hActiveHook)
  1907.                             hActiveHook.Execute();
  1908.  
  1909.                         oam.latch = oam.ram[0];
  1910.                         oam.buffered = oam.buffer;
  1911.                         oam.spriteZeroInLine = false;
  1912.                         oam.index = 0;
  1913.                         oam.phase = &Ppu::EvaluateSpritesPhase0;
  1914.                         cycles.hClock = 321;
  1915.  
  1916.                         if (cycles.count <= 321)
  1917.                             break;
  1918.  
  1919.                     case 321:
  1920.  
  1921.                         FetchName();
  1922.                         cycles.hClock = 322;
  1923.  
  1924.                         if (cycles.count <= 322)
  1925.                             break;
  1926.  
  1927.                     case 322:
  1928.  
  1929.                         OpenAttribute();
  1930.                         cycles.hClock = 323;
  1931.  
  1932.                         if (cycles.count <= 323)
  1933.                             break;
  1934.  
  1935.                     case 323:
  1936.  
  1937.                         FetchAttribute();
  1938.                         scroll.ClockX();
  1939.                         cycles.hClock = 324;
  1940.  
  1941.                         if (cycles.count <= 324)
  1942.                             break;
  1943.  
  1944.                     case 324:
  1945.  
  1946.                         OpenPattern( io.pattern | 0x0 );
  1947.                         cycles.hClock = 325;
  1948.  
  1949.                         if (cycles.count <= 325)
  1950.                             break;
  1951.  
  1952.                     case 325:
  1953.  
  1954.                         FetchBgPattern0();
  1955.                         cycles.hClock = 326;
  1956.  
  1957.                         if (cycles.count <= 326)
  1958.                             break;
  1959.  
  1960.                     case 326:
  1961.  
  1962.                         OpenPattern( io.pattern | 0x8 );
  1963.                         cycles.hClock = 327;
  1964.  
  1965.                         if (cycles.count <= 327)
  1966.                             break;
  1967.  
  1968.                     case 327:
  1969.  
  1970.                         FetchBgPattern1();
  1971.                         cycles.hClock = 328;
  1972.  
  1973.                         if (cycles.count <= 328)
  1974.                             break;
  1975.  
  1976.                     case 328:
  1977.  
  1978.                         PreLoadTiles();
  1979.                         OpenName();
  1980.                         cycles.hClock = 329;
  1981.  
  1982.                         if (cycles.count <= 329)
  1983.                             break;
  1984.  
  1985.                     case 329:
  1986.  
  1987.                         FetchName();
  1988.                         cycles.hClock = 330;
  1989.  
  1990.                         if (cycles.count <= 330)
  1991.                             break;
  1992.  
  1993.                     case 330:
  1994.  
  1995.                         OpenAttribute();
  1996.                         cycles.hClock = 331;
  1997.  
  1998.                         if (cycles.count <= 331)
  1999.                             break;
  2000.  
  2001.                     case 331:
  2002.  
  2003.                         FetchAttribute();
  2004.                         scroll.ClockX();
  2005.                         cycles.hClock = 332;
  2006.  
  2007.                         if (cycles.count <= 332)
  2008.                             break;
  2009.  
  2010.                     case 332:
  2011.  
  2012.                         OpenPattern( io.pattern | 0x0 );
  2013.                         cycles.hClock = 333;
  2014.  
  2015.                         if (cycles.count <= 333)
  2016.                             break;
  2017.  
  2018.                     case 333:
  2019.  
  2020.                         FetchBgPattern0();
  2021.                         cycles.hClock = 334;
  2022.  
  2023.                         if (cycles.count <= 334)
  2024.                             break;
  2025.  
  2026.                     case 334:
  2027.  
  2028.                         OpenPattern( io.pattern | 0x8 );
  2029.                         cycles.hClock = 335;
  2030.  
  2031.                         if (cycles.count <= 335)
  2032.                             break;
  2033.  
  2034.                     case 335:
  2035.  
  2036.                         FetchBgPattern1();
  2037.                         cycles.hClock = 336;
  2038.  
  2039.                         if (cycles.count <= 336)
  2040.                             break;
  2041.  
  2042.                     case 336:
  2043.  
  2044.                         OpenName();
  2045.                         cycles.hClock = 337;
  2046.  
  2047.                         if (cycles.count <= 337)
  2048.                             break;
  2049.  
  2050.                     case 337:
  2051.  
  2052.                         tiles.mask = tiles.show[1];
  2053.                         oam.mask = oam.show[1];
  2054.  
  2055.                         if (scanline == SCANLINE_HDUMMY && model == PPU_RP2C02)
  2056.                         {
  2057.                             if (regs.frame)
  2058.                             {
  2059.                                 output.burstPhase = (output.burstPhase + 2) % 3;
  2060.                                 cpu.SetFrameCycles( PPU_RP2C02_HVSYNC_1 );
  2061.                             }
  2062.                             else
  2063.                             {
  2064.                                 output.burstPhase = (output.burstPhase + 1) % 3;
  2065.                             }
  2066.                         }
  2067.  
  2068.                         cycles.hClock = 338;
  2069.  
  2070.                         if (cycles.count <= 338)
  2071.                             break;
  2072.  
  2073.                     case 338:
  2074.  
  2075.                         OpenName();
  2076.  
  2077.                         if (scanline++ != 239)
  2078.                         {
  2079.                             const uint line = (scanline != 0 || model != PPU_RP2C02 || !regs.frame ? 341 : 340);
  2080.  
  2081.                             cycles.hClock = 0;
  2082.                             cycles.vClock += line;
  2083.  
  2084.                             if (cycles.count <= line)
  2085.                                 break;
  2086.  
  2087.                             cycles.count -= line;
  2088.  
  2089.                             goto HActive;
  2090.                         }
  2091.                         else
  2092.                         {
  2093.                             cycles.hClock = HCLOCK_POSTRENDER;
  2094.  
  2095.                             if (cycles.count <= HCLOCK_POSTRENDER)
  2096.                                 break;
  2097.                         }
  2098.  
  2099.                     case HCLOCK_POSTRENDER:
  2100.                         UpdateAddressLine(scroll.address & 0x3fff);
  2101.                         cycles.hClock = HCLOCK_VBLANK_0;
  2102.  
  2103.                         if (cycles.count <= HCLOCK_VBLANK_0)
  2104.                             break;
  2105.  
  2106.                     case HCLOCK_VBLANK_0:
  2107.                     VBlank0:
  2108.  
  2109.                         regs.status |= Regs::STATUS_VBLANKING;
  2110.                         cycles.hClock = HCLOCK_VBLANK_1;
  2111.  
  2112.                         if (cycles.count <= HCLOCK_VBLANK_1)
  2113.                             break;
  2114.  
  2115.                     case HCLOCK_VBLANK_1:
  2116.                     VBlank1:
  2117.  
  2118.                         regs.status = (regs.status & 0xFF) | (regs.status >> 1 & Regs::STATUS_VBLANK);
  2119.                         oam.visible = oam.output;
  2120.                         cycles.hClock = HCLOCK_VBLANK_2;
  2121.  
  2122.                         if (cycles.count <= HCLOCK_VBLANK_2)
  2123.                             break;
  2124.  
  2125.                     case HCLOCK_VBLANK_2:
  2126.                     VBlank2:
  2127.  
  2128.                         cycles.hClock = HCLOCK_DUMMY;
  2129.                         cycles.count = Cpu::CYCLE_MAX;
  2130.                         cycles.reset = 0;
  2131.  
  2132.                         if (regs.ctrl[0] & regs.status & Regs::CTRL0_NMI)
  2133.                             cpu.DoNMI( cpu.GetFrameCycles() );
  2134.  
  2135.                         return;
  2136.  
  2137.                     case HCLOCK_BOOT:
  2138.                         goto Boot;
  2139.  
  2140.                     case HCLOCK_DUMMY+0:
  2141.  
  2142.                         regs.status = 0;
  2143.                         scanline = SCANLINE_HDUMMY;
  2144.  
  2145.                     case HCLOCK_DUMMY+8:
  2146.                     case HCLOCK_DUMMY+16:
  2147.                     case HCLOCK_DUMMY+24:
  2148.                     case HCLOCK_DUMMY+32:
  2149.                     case HCLOCK_DUMMY+40:
  2150.                     case HCLOCK_DUMMY+48:
  2151.                     case HCLOCK_DUMMY+56:
  2152.                     case HCLOCK_DUMMY+64:
  2153.                     case HCLOCK_DUMMY+72:
  2154.                     case HCLOCK_DUMMY+80:
  2155.                     case HCLOCK_DUMMY+88:
  2156.                     case HCLOCK_DUMMY+96:
  2157.                     case HCLOCK_DUMMY+104:
  2158.                     case HCLOCK_DUMMY+112:
  2159.                     case HCLOCK_DUMMY+120:
  2160.                     case HCLOCK_DUMMY+128:
  2161.                     case HCLOCK_DUMMY+136:
  2162.                     case HCLOCK_DUMMY+144:
  2163.                     case HCLOCK_DUMMY+152:
  2164.                     case HCLOCK_DUMMY+160:
  2165.                     case HCLOCK_DUMMY+168:
  2166.                     case HCLOCK_DUMMY+176:
  2167.                     case HCLOCK_DUMMY+184:
  2168.                     case HCLOCK_DUMMY+192:
  2169.                     case HCLOCK_DUMMY+200:
  2170.                     case HCLOCK_DUMMY+208:
  2171.                     case HCLOCK_DUMMY+216:
  2172.                     case HCLOCK_DUMMY+224:
  2173.                     case HCLOCK_DUMMY+232:
  2174.                     case HCLOCK_DUMMY+240:
  2175.                     case HCLOCK_DUMMY+248:
  2176.                     HDummyBg:
  2177.  
  2178.                         OpenName();
  2179.                         cycles.hClock += 2;
  2180.  
  2181.                         if (cycles.count <= cycles.hClock)
  2182.                             break;
  2183.  
  2184.                     case HCLOCK_DUMMY+2:
  2185.                     case HCLOCK_DUMMY+10:
  2186.                     case HCLOCK_DUMMY+18:
  2187.                     case HCLOCK_DUMMY+26:
  2188.                     case HCLOCK_DUMMY+34:
  2189.                     case HCLOCK_DUMMY+42:
  2190.                     case HCLOCK_DUMMY+50:
  2191.                     case HCLOCK_DUMMY+58:
  2192.                     case HCLOCK_DUMMY+66:
  2193.                     case HCLOCK_DUMMY+74:
  2194.                     case HCLOCK_DUMMY+82:
  2195.                     case HCLOCK_DUMMY+90:
  2196.                     case HCLOCK_DUMMY+98:
  2197.                     case HCLOCK_DUMMY+106:
  2198.                     case HCLOCK_DUMMY+114:
  2199.                     case HCLOCK_DUMMY+122:
  2200.                     case HCLOCK_DUMMY+130:
  2201.                     case HCLOCK_DUMMY+138:
  2202.                     case HCLOCK_DUMMY+146:
  2203.                     case HCLOCK_DUMMY+154:
  2204.                     case HCLOCK_DUMMY+162:
  2205.                     case HCLOCK_DUMMY+170:
  2206.                     case HCLOCK_DUMMY+178:
  2207.                     case HCLOCK_DUMMY+186:
  2208.                     case HCLOCK_DUMMY+194:
  2209.                     case HCLOCK_DUMMY+202:
  2210.                     case HCLOCK_DUMMY+210:
  2211.                     case HCLOCK_DUMMY+218:
  2212.                     case HCLOCK_DUMMY+226:
  2213.                     case HCLOCK_DUMMY+234:
  2214.                     case HCLOCK_DUMMY+242:
  2215.                     case HCLOCK_DUMMY+250:
  2216.  
  2217.                         OpenAttribute();
  2218.                         cycles.hClock += 2;
  2219.  
  2220.                         if (cycles.count <= cycles.hClock)
  2221.                             break;
  2222.  
  2223.                     case HCLOCK_DUMMY+4:
  2224.                     case HCLOCK_DUMMY+12:
  2225.                     case HCLOCK_DUMMY+20:
  2226.                     case HCLOCK_DUMMY+28:
  2227.                     case HCLOCK_DUMMY+36:
  2228.                     case HCLOCK_DUMMY+44:
  2229.                     case HCLOCK_DUMMY+52:
  2230.                     case HCLOCK_DUMMY+60:
  2231.                     case HCLOCK_DUMMY+68:
  2232.                     case HCLOCK_DUMMY+76:
  2233.                     case HCLOCK_DUMMY+84:
  2234.                     case HCLOCK_DUMMY+92:
  2235.                     case HCLOCK_DUMMY+100:
  2236.                     case HCLOCK_DUMMY+108:
  2237.                     case HCLOCK_DUMMY+116:
  2238.                     case HCLOCK_DUMMY+124:
  2239.                     case HCLOCK_DUMMY+132:
  2240.                     case HCLOCK_DUMMY+140:
  2241.                     case HCLOCK_DUMMY+148:
  2242.                     case HCLOCK_DUMMY+156:
  2243.                     case HCLOCK_DUMMY+164:
  2244.                     case HCLOCK_DUMMY+172:
  2245.                     case HCLOCK_DUMMY+180:
  2246.                     case HCLOCK_DUMMY+188:
  2247.                     case HCLOCK_DUMMY+196:
  2248.                     case HCLOCK_DUMMY+204:
  2249.                     case HCLOCK_DUMMY+212:
  2250.                     case HCLOCK_DUMMY+220:
  2251.                     case HCLOCK_DUMMY+228:
  2252.                     case HCLOCK_DUMMY+236:
  2253.                     case HCLOCK_DUMMY+244:
  2254.                     case HCLOCK_DUMMY+252:
  2255.  
  2256.                         OpenPattern( regs.ctrl[0] << 8 & 0x1000 );
  2257.                         cycles.hClock += 2;
  2258.  
  2259.                         if (cycles.count <= cycles.hClock)
  2260.                             break;
  2261.  
  2262.                     case HCLOCK_DUMMY+6:
  2263.                     case HCLOCK_DUMMY+14:
  2264.                     case HCLOCK_DUMMY+22:
  2265.                     case HCLOCK_DUMMY+30:
  2266.                     case HCLOCK_DUMMY+38:
  2267.                     case HCLOCK_DUMMY+46:
  2268.                     case HCLOCK_DUMMY+54:
  2269.                     case HCLOCK_DUMMY+62:
  2270.                     case HCLOCK_DUMMY+70:
  2271.                     case HCLOCK_DUMMY+78:
  2272.                     case HCLOCK_DUMMY+86:
  2273.                     case HCLOCK_DUMMY+94:
  2274.                     case HCLOCK_DUMMY+102:
  2275.                     case HCLOCK_DUMMY+110:
  2276.                     case HCLOCK_DUMMY+118:
  2277.                     case HCLOCK_DUMMY+126:
  2278.                     case HCLOCK_DUMMY+134:
  2279.                     case HCLOCK_DUMMY+142:
  2280.                     case HCLOCK_DUMMY+150:
  2281.                     case HCLOCK_DUMMY+158:
  2282.                     case HCLOCK_DUMMY+166:
  2283.                     case HCLOCK_DUMMY+174:
  2284.                     case HCLOCK_DUMMY+182:
  2285.                     case HCLOCK_DUMMY+190:
  2286.                     case HCLOCK_DUMMY+198:
  2287.                     case HCLOCK_DUMMY+206:
  2288.                     case HCLOCK_DUMMY+214:
  2289.                     case HCLOCK_DUMMY+222:
  2290.                     case HCLOCK_DUMMY+230:
  2291.                     case HCLOCK_DUMMY+238:
  2292.                     case HCLOCK_DUMMY+246:
  2293.                     case HCLOCK_DUMMY+254:
  2294.  
  2295.                         OpenPattern( io.address | 0x8 );
  2296.                         cycles.hClock += 2;
  2297.  
  2298.                         if (cycles.count <= cycles.hClock)
  2299.                             break;
  2300.  
  2301.                         if (cycles.hClock != HCLOCK_DUMMY+256)
  2302.                             goto HDummyBg;
  2303.  
  2304.                     case HCLOCK_DUMMY+256:
  2305.                     case HCLOCK_DUMMY+264:
  2306.                     case HCLOCK_DUMMY+272:
  2307.                     case HCLOCK_DUMMY+280:
  2308.                     case HCLOCK_DUMMY+288:
  2309.                     case HCLOCK_DUMMY+296:
  2310.                     case HCLOCK_DUMMY+312:
  2311.                     HDummySp:
  2312.  
  2313.                         OpenName();
  2314.                         cycles.hClock += 2;
  2315.  
  2316.                         if (cycles.count <= cycles.hClock)
  2317.                             break;
  2318.  
  2319.                     case HCLOCK_DUMMY+258:
  2320.                     case HCLOCK_DUMMY+266:
  2321.                     case HCLOCK_DUMMY+274:
  2322.                     case HCLOCK_DUMMY+282:
  2323.                     case HCLOCK_DUMMY+290:
  2324.                     case HCLOCK_DUMMY+298:
  2325.                     case HCLOCK_DUMMY+306:
  2326.                     case HCLOCK_DUMMY+314:
  2327.  
  2328.                         OpenName();
  2329.                         cycles.hClock += 2;
  2330.  
  2331.                         if (cycles.count <= cycles.hClock)
  2332.                             break;
  2333.  
  2334.                     case HCLOCK_DUMMY+260:
  2335.                     case HCLOCK_DUMMY+268:
  2336.                     case HCLOCK_DUMMY+276:
  2337.                     case HCLOCK_DUMMY+284:
  2338.                     case HCLOCK_DUMMY+292:
  2339.                     case HCLOCK_DUMMY+300:
  2340.                     case HCLOCK_DUMMY+308:
  2341.                     case HCLOCK_DUMMY+316:
  2342.  
  2343.                         OpenPattern( OpenSprite() );
  2344.                         cycles.hClock += 2;
  2345.  
  2346.                         if (cycles.count <= cycles.hClock)
  2347.                             break;
  2348.  
  2349.                     case HCLOCK_DUMMY+262:
  2350.                     case HCLOCK_DUMMY+270:
  2351.                     case HCLOCK_DUMMY+278:
  2352.                     case HCLOCK_DUMMY+286:
  2353.                     case HCLOCK_DUMMY+294:
  2354.                     case HCLOCK_DUMMY+302:
  2355.                     case HCLOCK_DUMMY+310:
  2356.                     case HCLOCK_DUMMY+318:
  2357.  
  2358.                         OpenPattern( io.address | 0x8 );
  2359.  
  2360.                         if (cycles.hClock != HCLOCK_DUMMY+318)
  2361.                         {
  2362.                             cycles.hClock += 2;
  2363.  
  2364.                             if (cycles.count <= cycles.hClock)
  2365.                                 break;
  2366.  
  2367.                             if (cycles.hClock != HCLOCK_DUMMY+304)
  2368.                                 goto HDummySp;
  2369.                         }
  2370.                         else
  2371.                         {
  2372.                             cycles.hClock = 320;
  2373.                             cycles.vClock += HCLOCK_DUMMY;
  2374.                             cycles.count -= HCLOCK_DUMMY;
  2375.  
  2376.                             if (cycles.count <= cycles.hClock)
  2377.                                 break;
  2378.  
  2379.                             goto HBlankBg;
  2380.                         }
  2381.  
  2382.                     case HCLOCK_DUMMY+304:
  2383.  
  2384.                         scroll.address = scroll.latch;
  2385.                         goto HDummySp;
  2386.  
  2387.                     default:
  2388.  
  2389.                         NST_UNREACHABLE();
  2390.                 }
  2391.             }
  2392.             else
  2393.             {
  2394.                 switch (cycles.hClock)
  2395.                 {
  2396.                     case 0:
  2397.                     case 1:
  2398.                     case 2:
  2399.                     case 3:
  2400.                     case 4:
  2401.                     case 5:
  2402.                     case 6:
  2403.                     case 7:
  2404.                     case 8:
  2405.                     case 9:
  2406.                     case 10:
  2407.                     case 11:
  2408.                     case 12:
  2409.                     case 13:
  2410.                     case 14:
  2411.                     case 15:
  2412.                     case 16:
  2413.                     case 17:
  2414.                     case 18:
  2415.                     case 19:
  2416.                     case 20:
  2417.                     case 21:
  2418.                     case 22:
  2419.                     case 23:
  2420.                     case 24:
  2421.                     case 25:
  2422.                     case 26:
  2423.                     case 27:
  2424.                     case 28:
  2425.                     case 29:
  2426.                     case 30:
  2427.                     case 31:
  2428.                     case 32:
  2429.                     case 33:
  2430.                     case 34:
  2431.                     case 35:
  2432.                     case 36:
  2433.                     case 37:
  2434.                     case 38:
  2435.                     case 39:
  2436.                     case 40:
  2437.                     case 41:
  2438.                     case 42:
  2439.                     case 43:
  2440.                     case 44:
  2441.                     case 45:
  2442.                     case 46:
  2443.                     case 47:
  2444.                     case 48:
  2445.                     case 49:
  2446.                     case 50:
  2447.                     case 51:
  2448.                     case 52:
  2449.                     case 53:
  2450.                     case 54:
  2451.                     case 55:
  2452.                     case 56:
  2453.                     case 57:
  2454.                     case 58:
  2455.                     case 59:
  2456.                     case 60:
  2457.                     case 61:
  2458.                     case 62:
  2459.                     case 63:
  2460.                     case 64:
  2461.                     case 65:
  2462.                     case 66:
  2463.                     case 67:
  2464.                     case 68:
  2465.                     case 69:
  2466.                     case 70:
  2467.                     case 71:
  2468.                     case 72:
  2469.                     case 73:
  2470.                     case 74:
  2471.                     case 75:
  2472.                     case 76:
  2473.                     case 77:
  2474.                     case 78:
  2475.                     case 79:
  2476.                     case 80:
  2477.                     case 81:
  2478.                     case 82:
  2479.                     case 83:
  2480.                     case 84:
  2481.                     case 85:
  2482.                     case 86:
  2483.                     case 87:
  2484.                     case 88:
  2485.                     case 89:
  2486.                     case 90:
  2487.                     case 91:
  2488.                     case 92:
  2489.                     case 93:
  2490.                     case 94:
  2491.                     case 95:
  2492.                     case 96:
  2493.                     case 97:
  2494.                     case 98:
  2495.                     case 99:
  2496.                     case 100:
  2497.                     case 101:
  2498.                     case 102:
  2499.                     case 103:
  2500.                     case 104:
  2501.                     case 105:
  2502.                     case 106:
  2503.                     case 107:
  2504.                     case 108:
  2505.                     case 109:
  2506.                     case 110:
  2507.                     case 111:
  2508.                     case 112:
  2509.                     case 113:
  2510.                     case 114:
  2511.                     case 115:
  2512.                     case 116:
  2513.                     case 117:
  2514.                     case 118:
  2515.                     case 119:
  2516.                     case 120:
  2517.                     case 121:
  2518.                     case 122:
  2519.                     case 123:
  2520.                     case 124:
  2521.                     case 125:
  2522.                     case 126:
  2523.                     case 127:
  2524.                     case 128:
  2525.                     case 129:
  2526.                     case 130:
  2527.                     case 131:
  2528.                     case 132:
  2529.                     case 133:
  2530.                     case 134:
  2531.                     case 135:
  2532.                     case 136:
  2533.                     case 137:
  2534.                     case 138:
  2535.                     case 139:
  2536.                     case 140:
  2537.                     case 141:
  2538.                     case 142:
  2539.                     case 143:
  2540.                     case 144:
  2541.                     case 145:
  2542.                     case 146:
  2543.                     case 147:
  2544.                     case 148:
  2545.                     case 149:
  2546.                     case 150:
  2547.                     case 151:
  2548.                     case 152:
  2549.                     case 153:
  2550.                     case 154:
  2551.                     case 155:
  2552.                     case 156:
  2553.                     case 157:
  2554.                     case 158:
  2555.                     case 159:
  2556.                     case 160:
  2557.                     case 161:
  2558.                     case 162:
  2559.                     case 163:
  2560.                     case 164:
  2561.                     case 165:
  2562.                     case 166:
  2563.                     case 167:
  2564.                     case 168:
  2565.                     case 169:
  2566.                     case 170:
  2567.                     case 171:
  2568.                     case 172:
  2569.                     case 173:
  2570.                     case 174:
  2571.                     case 175:
  2572.                     case 176:
  2573.                     case 177:
  2574.                     case 178:
  2575.                     case 179:
  2576.                     case 180:
  2577.                     case 181:
  2578.                     case 182:
  2579.                     case 183:
  2580.                     case 184:
  2581.                     case 185:
  2582.                     case 186:
  2583.                     case 187:
  2584.                     case 188:
  2585.                     case 189:
  2586.                     case 190:
  2587.                     case 191:
  2588.                     case 192:
  2589.                     case 193:
  2590.                     case 194:
  2591.                     case 195:
  2592.                     case 196:
  2593.                     case 197:
  2594.                     case 198:
  2595.                     case 199:
  2596.                     case 200:
  2597.                     case 201:
  2598.                     case 202:
  2599.                     case 203:
  2600.                     case 204:
  2601.                     case 205:
  2602.                     case 206:
  2603.                     case 207:
  2604.                     case 208:
  2605.                     case 209:
  2606.                     case 210:
  2607.                     case 211:
  2608.                     case 212:
  2609.                     case 213:
  2610.                     case 214:
  2611.                     case 215:
  2612.                     case 216:
  2613.                     case 217:
  2614.                     case 218:
  2615.                     case 219:
  2616.                     case 220:
  2617.                     case 221:
  2618.                     case 222:
  2619.                     case 223:
  2620.                     case 224:
  2621.                     case 225:
  2622.                     case 226:
  2623.                     case 227:
  2624.                     case 228:
  2625.                     case 229:
  2626.                     case 230:
  2627.                     case 231:
  2628.                     case 232:
  2629.                     case 233:
  2630.                     case 234:
  2631.                     case 235:
  2632.                     case 236:
  2633.                     case 237:
  2634.                     case 238:
  2635.                     case 239:
  2636.                     case 240:
  2637.                     case 241:
  2638.                     case 242:
  2639.                     case 243:
  2640.                     case 244:
  2641.                     case 245:
  2642.                     case 246:
  2643.                     case 247:
  2644.                     case 248:
  2645.                     case 249:
  2646.                     case 250:
  2647.                     case 251:
  2648.                     case 252:
  2649.                     case 253:
  2650.                     case 254:
  2651.                     case 255:
  2652.                     HActiveOff:
  2653.                     {
  2654.                         const uint pixel = output.palette[(scroll.address & 0x3F00) == 0x3F00 ? (scroll.address & 0x001F) : 0];
  2655.  
  2656.                         uint i = cycles.hClock;
  2657.                         const uint hClock = NST_MIN(cycles.count,256);
  2658.                         NST_ASSERT( i < hClock );
  2659.  
  2660.                         cycles.hClock = hClock;
  2661.                         tiles.index = (hClock - 1) & 8;
  2662.  
  2663.                         byte* const NST_RESTRICT tile = tiles.pixels;
  2664.                         Video::Screen::Pixel* NST_RESTRICT target = output.target;
  2665.  
  2666.                         do
  2667.                         {
  2668.                             tile[i++ & 15] = 0;
  2669.                             *target++ = pixel;
  2670.                         }
  2671.                         while (i != hClock);
  2672.  
  2673.                         output.target = target;
  2674.  
  2675.                         if (cycles.count <= 256)
  2676.                             break;
  2677.                     }
  2678.  
  2679.                     case 256:
  2680.  
  2681.                         cycles.hClock = 257;
  2682.  
  2683.                         if (cycles.count <= 257)
  2684.                             break;
  2685.  
  2686.                     case 257:
  2687.  
  2688.                         if (hBlankHook)
  2689.                             hBlankHook.Execute();
  2690.  
  2691.                         oam.visible = oam.output;
  2692.                         cycles.hClock = 258;
  2693.  
  2694.                         if (cycles.count <= 258)
  2695.                             break;
  2696.  
  2697.                     case 258:
  2698.                     case 260:
  2699.                     case 261:
  2700.                     case 262:
  2701.                     case 263:
  2702.                     case 264:
  2703.                     case 266:
  2704.                     case 268:
  2705.                     case 269:
  2706.                     case 270:
  2707.                     case 271:
  2708.                     case 272:
  2709.                     case 274:
  2710.                     case 276:
  2711.                     case 277:
  2712.                     case 278:
  2713.                     case 279:
  2714.                     case 280:
  2715.                     case 282:
  2716.                     case 284:
  2717.                     case 285:
  2718.                     case 286:
  2719.                     case 287:
  2720.                     case 288:
  2721.                     case 290:
  2722.                     case 292:
  2723.                     case 293:
  2724.                     case 294:
  2725.                     case 295:
  2726.                     case 296:
  2727.                     case 298:
  2728.                     case 300:
  2729.                     case 301:
  2730.                     case 302:
  2731.                     case 303:
  2732.                     case 304:
  2733.                     case 306:
  2734.                     case 308:
  2735.                     case 309:
  2736.                     case 310:
  2737.                     case 311:
  2738.                     case 312:
  2739.                     case 314:
  2740.                     case 316:
  2741.                     case 317:
  2742.                     case 318:
  2743.                     case 319:
  2744.  
  2745.                         if (cycles.count <= 320)
  2746.                         {
  2747.                             cycles.hClock = cycles.count + ((cycles.count & 0x7) == 3 || (cycles.count & 0x7) == 1);
  2748.                             break;
  2749.                         }
  2750.  
  2751.                     case 320:
  2752.                     HBlankOff:
  2753.  
  2754.                         cycles.hClock = 321;
  2755.  
  2756.                         if (hActiveHook)
  2757.                             hActiveHook.Execute();
  2758.  
  2759.                         oam.buffered = oam.buffer;
  2760.                         oam.spriteZeroInLine = false;
  2761.                         oam.index = 0;
  2762.                         oam.phase = &Ppu::EvaluateSpritesPhase0;
  2763.  
  2764.                         if (cycles.count <= 321)
  2765.                             break;
  2766.  
  2767.                     case 321:
  2768.                     case 322:
  2769.                     case 323:
  2770.                     case 324:
  2771.                     case 325:
  2772.                     case 326:
  2773.                     case 327:
  2774.                     case 328:
  2775.                     case 329:
  2776.                     case 330:
  2777.                     case 331:
  2778.                     case 332:
  2779.                     case 333:
  2780.                     case 334:
  2781.                     case 335:
  2782.                     case 336:
  2783.                     case 337:
  2784.  
  2785.                         cycles.hClock = cycles.count;
  2786.  
  2787.                         if (cycles.count <= 338)
  2788.                             break;
  2789.  
  2790.                     case 338:
  2791.  
  2792.                         if (scanline++ != 239)
  2793.                         {
  2794.                             tiles.mask = tiles.show[1];
  2795.                             oam.mask = oam.show[1];
  2796.  
  2797.                             if (scanline == 0 && model == PPU_RP2C02)
  2798.                                 output.burstPhase = (output.burstPhase + 1) % 3;
  2799.  
  2800.                             cycles.vClock += 341;
  2801.                             cycles.hClock = 0;
  2802.  
  2803.                             if (cycles.count <= 341)
  2804.                                 break;
  2805.  
  2806.                             cycles.count -= 341;
  2807.  
  2808.                             goto HActiveOff;
  2809.                         }
  2810.                         else
  2811.                         {
  2812.                             cycles.hClock = HCLOCK_VBLANK_0;
  2813.  
  2814.                             if (cycles.count <= HCLOCK_VBLANK_0)
  2815.                                 break;
  2816.                         }
  2817.  
  2818.                     case HCLOCK_VBLANK_0:
  2819.                         goto VBlank0;
  2820.  
  2821.                     case HCLOCK_VBLANK_1:
  2822.                         goto VBlank1;
  2823.  
  2824.                     case HCLOCK_VBLANK_2:
  2825.                         goto VBlank2;
  2826.  
  2827.                     case HCLOCK_BOOT:
  2828.                     Boot:
  2829.  
  2830.                         regs.status |= Regs::STATUS_VBLANK;
  2831.                         cycles.hClock = HCLOCK_DUMMY;
  2832.                         cycles.count = Cpu::CYCLE_MAX;
  2833.  
  2834.                         if (cycles.reset)
  2835.                         {
  2836.                             switch (model)
  2837.                             {
  2838.                                 case PPU_RP2C07: cycles.reset = PPU_RP2C07_HVREGBOOT - PPU_RP2C07_HVSYNCBOOT; break;
  2839.                                 case PPU_DENDY:  cycles.reset = PPU_DENDY_HVREGBOOT  - PPU_DENDY_HVSYNCBOOT;  break;
  2840.                                 default:         cycles.reset = PPU_RP2C02_HVREGBOOT - PPU_RP2C02_HVSYNCBOOT; break;
  2841.                             }
  2842.                         }
  2843.                         return;
  2844.  
  2845.                     case HCLOCK_DUMMY+0:
  2846.  
  2847.                         regs.status = 0;
  2848.                         scanline = SCANLINE_HDUMMY;
  2849.  
  2850.                     case HCLOCK_DUMMY+2:
  2851.                     case HCLOCK_DUMMY+4:
  2852.                     case HCLOCK_DUMMY+6:
  2853.                     case HCLOCK_DUMMY+8:
  2854.                     case HCLOCK_DUMMY+10:
  2855.                     case HCLOCK_DUMMY+12:
  2856.                     case HCLOCK_DUMMY+14:
  2857.                     case HCLOCK_DUMMY+16:
  2858.                     case HCLOCK_DUMMY+18:
  2859.                     case HCLOCK_DUMMY+20:
  2860.                     case HCLOCK_DUMMY+22:
  2861.                     case HCLOCK_DUMMY+24:
  2862.                     case HCLOCK_DUMMY+26:
  2863.                     case HCLOCK_DUMMY+28:
  2864.                     case HCLOCK_DUMMY+30:
  2865.                     case HCLOCK_DUMMY+32:
  2866.                     case HCLOCK_DUMMY+34:
  2867.                     case HCLOCK_DUMMY+36:
  2868.                     case HCLOCK_DUMMY+38:
  2869.                     case HCLOCK_DUMMY+40:
  2870.                     case HCLOCK_DUMMY+42:
  2871.                     case HCLOCK_DUMMY+44:
  2872.                     case HCLOCK_DUMMY+46:
  2873.                     case HCLOCK_DUMMY+48:
  2874.                     case HCLOCK_DUMMY+50:
  2875.                     case HCLOCK_DUMMY+52:
  2876.                     case HCLOCK_DUMMY+54:
  2877.                     case HCLOCK_DUMMY+56:
  2878.                     case HCLOCK_DUMMY+58:
  2879.                     case HCLOCK_DUMMY+60:
  2880.                     case HCLOCK_DUMMY+62:
  2881.                     case HCLOCK_DUMMY+64:
  2882.                     case HCLOCK_DUMMY+66:
  2883.                     case HCLOCK_DUMMY+68:
  2884.                     case HCLOCK_DUMMY+70:
  2885.                     case HCLOCK_DUMMY+72:
  2886.                     case HCLOCK_DUMMY+74:
  2887.                     case HCLOCK_DUMMY+76:
  2888.                     case HCLOCK_DUMMY+78:
  2889.                     case HCLOCK_DUMMY+80:
  2890.                     case HCLOCK_DUMMY+82:
  2891.                     case HCLOCK_DUMMY+84:
  2892.                     case HCLOCK_DUMMY+86:
  2893.                     case HCLOCK_DUMMY+88:
  2894.                     case HCLOCK_DUMMY+90:
  2895.                     case HCLOCK_DUMMY+92:
  2896.                     case HCLOCK_DUMMY+94:
  2897.                     case HCLOCK_DUMMY+96:
  2898.                     case HCLOCK_DUMMY+98:
  2899.                     case HCLOCK_DUMMY+100:
  2900.                     case HCLOCK_DUMMY+102:
  2901.                     case HCLOCK_DUMMY+104:
  2902.                     case HCLOCK_DUMMY+106:
  2903.                     case HCLOCK_DUMMY+108:
  2904.                     case HCLOCK_DUMMY+110:
  2905.                     case HCLOCK_DUMMY+112:
  2906.                     case HCLOCK_DUMMY+114:
  2907.                     case HCLOCK_DUMMY+116:
  2908.                     case HCLOCK_DUMMY+118:
  2909.                     case HCLOCK_DUMMY+120:
  2910.                     case HCLOCK_DUMMY+122:
  2911.                     case HCLOCK_DUMMY+124:
  2912.                     case HCLOCK_DUMMY+126:
  2913.                     case HCLOCK_DUMMY+128:
  2914.                     case HCLOCK_DUMMY+130:
  2915.                     case HCLOCK_DUMMY+132:
  2916.                     case HCLOCK_DUMMY+134:
  2917.                     case HCLOCK_DUMMY+136:
  2918.                     case HCLOCK_DUMMY+138:
  2919.                     case HCLOCK_DUMMY+140:
  2920.                     case HCLOCK_DUMMY+142:
  2921.                     case HCLOCK_DUMMY+144:
  2922.                     case HCLOCK_DUMMY+146:
  2923.                     case HCLOCK_DUMMY+148:
  2924.                     case HCLOCK_DUMMY+150:
  2925.                     case HCLOCK_DUMMY+152:
  2926.                     case HCLOCK_DUMMY+154:
  2927.                     case HCLOCK_DUMMY+156:
  2928.                     case HCLOCK_DUMMY+158:
  2929.                     case HCLOCK_DUMMY+160:
  2930.                     case HCLOCK_DUMMY+162:
  2931.                     case HCLOCK_DUMMY+164:
  2932.                     case HCLOCK_DUMMY+166:
  2933.                     case HCLOCK_DUMMY+168:
  2934.                     case HCLOCK_DUMMY+170:
  2935.                     case HCLOCK_DUMMY+172:
  2936.                     case HCLOCK_DUMMY+174:
  2937.                     case HCLOCK_DUMMY+176:
  2938.                     case HCLOCK_DUMMY+178:
  2939.                     case HCLOCK_DUMMY+180:
  2940.                     case HCLOCK_DUMMY+182:
  2941.                     case HCLOCK_DUMMY+184:
  2942.                     case HCLOCK_DUMMY+186:
  2943.                     case HCLOCK_DUMMY+188:
  2944.                     case HCLOCK_DUMMY+190:
  2945.                     case HCLOCK_DUMMY+192:
  2946.                     case HCLOCK_DUMMY+194:
  2947.                     case HCLOCK_DUMMY+196:
  2948.                     case HCLOCK_DUMMY+198:
  2949.                     case HCLOCK_DUMMY+200:
  2950.                     case HCLOCK_DUMMY+202:
  2951.                     case HCLOCK_DUMMY+204:
  2952.                     case HCLOCK_DUMMY+206:
  2953.                     case HCLOCK_DUMMY+208:
  2954.                     case HCLOCK_DUMMY+210:
  2955.                     case HCLOCK_DUMMY+212:
  2956.                     case HCLOCK_DUMMY+214:
  2957.                     case HCLOCK_DUMMY+216:
  2958.                     case HCLOCK_DUMMY+218:
  2959.                     case HCLOCK_DUMMY+220:
  2960.                     case HCLOCK_DUMMY+222:
  2961.                     case HCLOCK_DUMMY+224:
  2962.                     case HCLOCK_DUMMY+226:
  2963.                     case HCLOCK_DUMMY+228:
  2964.                     case HCLOCK_DUMMY+230:
  2965.                     case HCLOCK_DUMMY+232:
  2966.                     case HCLOCK_DUMMY+234:
  2967.                     case HCLOCK_DUMMY+236:
  2968.                     case HCLOCK_DUMMY+238:
  2969.                     case HCLOCK_DUMMY+240:
  2970.                     case HCLOCK_DUMMY+242:
  2971.                     case HCLOCK_DUMMY+244:
  2972.                     case HCLOCK_DUMMY+246:
  2973.                     case HCLOCK_DUMMY+248:
  2974.                     case HCLOCK_DUMMY+250:
  2975.                     case HCLOCK_DUMMY+252:
  2976.                     case HCLOCK_DUMMY+254:
  2977.                     case HCLOCK_DUMMY+256:
  2978.                     case HCLOCK_DUMMY+258:
  2979.                     case HCLOCK_DUMMY+260:
  2980.                     case HCLOCK_DUMMY+262:
  2981.                     case HCLOCK_DUMMY+264:
  2982.                     case HCLOCK_DUMMY+266:
  2983.                     case HCLOCK_DUMMY+268:
  2984.                     case HCLOCK_DUMMY+270:
  2985.                     case HCLOCK_DUMMY+272:
  2986.                     case HCLOCK_DUMMY+274:
  2987.                     case HCLOCK_DUMMY+276:
  2988.                     case HCLOCK_DUMMY+278:
  2989.                     case HCLOCK_DUMMY+280:
  2990.                     case HCLOCK_DUMMY+282:
  2991.                     case HCLOCK_DUMMY+284:
  2992.                     case HCLOCK_DUMMY+286:
  2993.                     case HCLOCK_DUMMY+288:
  2994.                     case HCLOCK_DUMMY+290:
  2995.                     case HCLOCK_DUMMY+292:
  2996.                     case HCLOCK_DUMMY+294:
  2997.                     case HCLOCK_DUMMY+296:
  2998.                     case HCLOCK_DUMMY+298:
  2999.                     case HCLOCK_DUMMY+300:
  3000.                     case HCLOCK_DUMMY+302:
  3001.                     case HCLOCK_DUMMY+304:
  3002.                     case HCLOCK_DUMMY+306:
  3003.                     case HCLOCK_DUMMY+308:
  3004.                     case HCLOCK_DUMMY+310:
  3005.                     case HCLOCK_DUMMY+312:
  3006.                     case HCLOCK_DUMMY+314:
  3007.                     case HCLOCK_DUMMY+316:
  3008.                     {
  3009.                         NST_COMPILE_ASSERT( HCLOCK_DUMMY & 1 );
  3010.  
  3011.                         cycles.hClock = cycles.count | 1;
  3012.  
  3013.                         if (cycles.count <= HCLOCK_DUMMY+318)
  3014.                             break;
  3015.                     }
  3016.  
  3017.                     case HCLOCK_DUMMY+318:
  3018.  
  3019.                         cycles.hClock = 320;
  3020.                         cycles.vClock += HCLOCK_DUMMY;
  3021.                         cycles.count -= HCLOCK_DUMMY;
  3022.  
  3023.                         if (cycles.count <= 320)
  3024.                             break;
  3025.  
  3026.                         goto HBlankOff;
  3027.  
  3028.                     default:
  3029.  
  3030.                         NST_UNREACHABLE();
  3031.                 }
  3032.             }
  3033.  
  3034.             cycles.count = GetCycles();
  3035.         }
  3036.     }
  3037. }
Advertisement
Add Comment
Please, Sign In to add comment