| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485 |
- ////////////////////////////////////////////////////////////////////////////////////////
- //
- // Nestopia - NES/Famicom emulator written in C++
- //
- // Copyright (C) 2003-2008 Martin Freij
- //
- // This file is part of Nestopia.
- //
- // Nestopia is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // Nestopia is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with Nestopia; if not, write to the Free Software
- // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- //
- ////////////////////////////////////////////////////////////////////////////////////////
- #include <cstring>
- #include "NstCpu.hpp"
- #include "NstPpu.hpp"
- #include "NstState.hpp"
- namespace Nes
- {
- namespace Core
- {
- #ifdef NST_MSVC_OPTIMIZE
- #pragma optimize("s", on)
- #endif
- const byte Ppu::yuvMaps[4][0x40] =
- {
- {
- 0x35, 0x23, 0x16, 0x22, 0x1C, 0x09, 0x2D, 0x15,
- 0x20, 0x00, 0x27, 0x05, 0x04, 0x28, 0x08, 0x20,
- 0x21, 0x27, 0x07, 0x29, 0x3C, 0x32, 0x36, 0x12,
- 0x28, 0x2B, 0x0D, 0x08, 0x10, 0x3D, 0x24, 0x01,
- 0x01, 0x31, 0x33, 0x2A, 0x2C, 0x0C, 0x1B, 0x14,
- 0x0D, 0x07, 0x34, 0x06, 0x13, 0x02, 0x26, 0x0D,
- 0x0D, 0x19, 0x10, 0x0A, 0x39, 0x03, 0x37, 0x17,
- 0x09, 0x11, 0x1A, 0x1D, 0x38, 0x25, 0x18, 0x3A
- },
- {
- 0x0D, 0x27, 0x18, 0x39, 0x3A, 0x25, 0x1C, 0x31,
- 0x16, 0x13, 0x38, 0x34, 0x20, 0x23, 0x3C, 0x1A,
- 0x09, 0x21, 0x06, 0x10, 0x1B, 0x29, 0x08, 0x22,
- 0x2D, 0x24, 0x01, 0x2B, 0x32, 0x08, 0x0D, 0x03,
- 0x04, 0x36, 0x26, 0x33, 0x11, 0x07, 0x10, 0x02,
- 0x14, 0x28, 0x00, 0x09, 0x12, 0x0D, 0x28, 0x20,
- 0x27, 0x1D, 0x2A, 0x17, 0x0C, 0x01, 0x15, 0x19,
- 0x0D, 0x2C, 0x07, 0x37, 0x35, 0x05, 0x0A, 0x3D
- },
- {
- 0x14, 0x25, 0x3A, 0x10, 0x1A, 0x20, 0x31, 0x09,
- 0x01, 0x0D, 0x36, 0x08, 0x15, 0x10, 0x27, 0x3C,
- 0x22, 0x1C, 0x05, 0x12, 0x19, 0x18, 0x17, 0x1B,
- 0x00, 0x03, 0x0D, 0x02, 0x16, 0x06, 0x34, 0x35,
- 0x23, 0x09, 0x01, 0x37, 0x1D, 0x27, 0x26, 0x20,
- 0x29, 0x04, 0x21, 0x24, 0x11, 0x3D, 0x0D, 0x07,
- 0x2C, 0x08, 0x39, 0x33, 0x07, 0x2A, 0x28, 0x2D,
- 0x0A, 0x0D, 0x32, 0x38, 0x13, 0x2B, 0x28, 0x0C
- },
- {
- 0x18, 0x03, 0x1C, 0x28, 0x0D, 0x35, 0x01, 0x17,
- 0x10, 0x07, 0x2A, 0x01, 0x36, 0x37, 0x1A, 0x39,
- 0x25, 0x08, 0x12, 0x34, 0x0D, 0x2D, 0x06, 0x26,
- 0x27, 0x1B, 0x22, 0x19, 0x04, 0x0D, 0x3A, 0x21,
- 0x05, 0x0A, 0x07, 0x02, 0x13, 0x14, 0x00, 0x15,
- 0x0C, 0x10, 0x11, 0x09, 0x1D, 0x38, 0x3D, 0x24,
- 0x33, 0x20, 0x08, 0x16, 0x28, 0x2B, 0x20, 0x3C,
- 0x0D, 0x27, 0x23, 0x31, 0x29, 0x32, 0x2C, 0x09
- }
- };
- Ppu::Tiles::Tiles()
- : padding0(0), padding1(0) {}
- Ppu::Oam::Oam()
- : limit(buffer + STD_LINE_SPRITES*4), spriteLimit(true) {}
- Ppu::Output::Output(Video::Screen::Pixel* p)
- : pixels(p) {}
- Ppu::TileLut::TileLut()
- {
- for (uint i=0; i < 0x400; ++i)
- {
- block[i][0] = (i & 0xC0) ? (i >> 6 & 0xC) | (i >> 6 & 0x3) : 0;
- block[i][1] = (i & 0x30) ? (i >> 6 & 0xC) | (i >> 4 & 0x3) : 0;
- block[i][2] = (i & 0x0C) ? (i >> 6 & 0xC) | (i >> 2 & 0x3) : 0;
- block[i][3] = (i & 0x03) ? (i >> 6 & 0xC) | (i >> 0 & 0x3) : 0;
- }
- }
- Ppu::Ppu(Cpu& c)
- :
- cpu (c),
- output (screen.pixels),
- model (PPU_RP2C02),
- rgbMap (NULL),
- yuvMap (NULL)
- {
- cycles.one = PPU_RP2C02_CC;
- overclocked = false;
- PowerOff();
- }
- void Ppu::PowerOff()
- {
- Reset( true, false, false );
- }
- void Ppu::Reset(bool hard,bool acknowledged)
- {
- Reset( hard, acknowledged, true );
- }
- void Ppu::Reset(const bool hard,const bool acknowledged,const bool map)
- {
- if (map)
- {
- for (uint i=0x2000; i < 0x4000; i += 0x8)
- {
- cpu.Map( i+0 ).Set( this, i != 0x3000 ? &Ppu::Peek_2xxx : &Ppu::Peek_3000, &Ppu::Poke_2000 );
- cpu.Map( i+1 ).Set( this, &Ppu::Peek_2xxx, &Ppu::Poke_2001 );
- cpu.Map( i+2 ).Set( this, &Ppu::Peek_2002, &Ppu::Poke_2xxx );
- cpu.Map( i+3 ).Set( this, &Ppu::Peek_2xxx, &Ppu::Poke_2003 );
- cpu.Map( i+4 ).Set( this, &Ppu::Peek_2004, &Ppu::Poke_2004 );
- cpu.Map( i+5 ).Set( this, &Ppu::Peek_2xxx, &Ppu::Poke_2005 );
- cpu.Map( i+6 ).Set( this, &Ppu::Peek_2xxx, &Ppu::Poke_2006 );
- cpu.Map( i+7 ).Set( this, &Ppu::Peek_2007, &Ppu::Poke_2007 );
- }
- if (model == PPU_RC2C05_01 || model == PPU_RC2C05_04)
- {
- for (uint i=0x2002; i < 0x4000; i += 0x8)
- cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_01_04 );
- }
- else if (model == PPU_RC2C05_02)
- {
- for (uint i=0x2002; i < 0x4000; i += 0x8)
- cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_02 );
- }
- else if (model == PPU_RC2C05_03)
- {
- for (uint i=0x2002; i < 0x4000; i += 0x8)
- cpu.Map( i ).Set( &Ppu::Peek_2002_RC2C05_03 );
- }
- else if (model == PPU_RC2C05_05)
- {
- for (uint i=0x2000; i < 0x4000; i += 0x8)
- {
- cpu.Map( i+0 ).Set( &Ppu::Poke_2001 );
- cpu.Map( i+1 ).Set( &Ppu::Poke_2000 );
- }
- }
- cpu.Map( 0x4014U ).Set( this, &Ppu::Peek_4014, &Ppu::Poke_4014 );
- }
- if (hard)
- {
- static const byte powerUpPalette[] =
- {
- 0x3F,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,
- 0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
- 0x09,0x01,0x34,0x03,0x00,0x04,0x00,0x14,
- 0x08,0x3A,0x00,0x02,0x00,0x20,0x2C,0x08
- };
- std::memcpy( palette.ram, powerUpPalette, Palette::SIZE );
- std::memset( oam.ram, Oam::GARBAGE, Oam::SIZE );
- std::memset( nameTable.ram, NameTable::GARBAGE, NameTable::SIZE );
- io.latch = 0;
- io.buffer = Io::BUFFER_GARBAGE;
- regs.status = 0;
- regs.ctrl[0] = 0;
- regs.ctrl[1] = 0;
- regs.frame = 0;
- regs.oam = 0;
- scroll.latch = 0;
- scroll.xFine = 0;
- scroll.toggle = 0;
- scroll.address = 0;
- output.burstPhase = 0;
- cycles.reset = 0;
- cycles.hClock = HCLOCK_BOOT;
- }
- else if (acknowledged)
- {
- io.buffer = 0;
- regs.status = 0;
- regs.ctrl[0] = 0;
- regs.ctrl[1] = 0;
- scroll.latch = 0;
- scroll.xFine = 0;
- scroll.toggle = 0;
- cycles.reset = Cpu::CYCLE_MAX;
- cycles.hClock = HCLOCK_BOOT;
- std::memset( oam.ram, Oam::GARBAGE, Oam::SIZE );
- }
- else
- {
- cycles.hClock = HCLOCK_DUMMY;
- cycles.reset = 0;
- }
- if (chr.Source().Empty())
- {
- chr.Source().Set( Ram::RAM, true, false, NameTable::SIZE, nameTable.ram );
- chr.SwapBanks<SIZE_2K,0x0000>(0,0,0,0);
- }
- if (nmt.Source().Empty())
- {
- nmt.Source().Set( Ram::RAM, true, true, NameTable::SIZE, nameTable.ram );
- nmt.SwapBanks<SIZE_2K,0x0000>(0,0);
- }
- chr.ResetAccessor();
- nmt.ResetAccessors();
- cycles.vClock = 0;
- cycles.count = Cpu::CYCLE_MAX;
- scanline = SCANLINE_VBLANK;
- scanline_sleep = -1;
- ssleep = -1;
- io.address = 0;
- io.pattern = 0;
- io.line.Unset();
- tiles.pattern[0] = 0;
- tiles.pattern[1] = 0;
- tiles.attribute = 0;
- tiles.index = 8;
- tiles.mask = 0;
- oam.index = 0;
- oam.address = 0;
- oam.latch = 0;
- oam.spriteZeroInLine = false;
- oam.phase = &Ppu::EvaluateSpritesPhase0;
- oam.buffered = oam.buffer;
- oam.visible = oam.output;
- oam.mask = 0;
- output.target = NULL;
- hActiveHook.Unset();
- hBlankHook.Unset();
- UpdateStates();
- screen.Clear();
- }
- uint Ppu::SetAddressLineHook(const Core::Io::Line& line)
- {
- io.line = line;
- return io.address;
- }
- void Ppu::SetHActiveHook(const Hook& hook)
- {
- hActiveHook = hook;
- }
- void Ppu::SetHBlankHook(const Hook& hook)
- {
- hBlankHook = hook;
- }
- void Ppu::UpdateStates()
- {
- oam.height = (regs.ctrl[0] >> 2 & 8) + 8;
- tiles.show[0] = (regs.ctrl[1] & Regs::CTRL1_BG_ENABLED) ? 0xFF : 0x00;
- tiles.show[1] = (regs.ctrl[1] & Regs::CTRL1_BG_ENABLED_NO_CLIP) == Regs::CTRL1_BG_ENABLED_NO_CLIP ? 0xFF : 0x00;
- oam.show[0] = (regs.ctrl[1] & Regs::CTRL1_SP_ENABLED) ? 0xFF : 0x00;
- oam.show[1] = (regs.ctrl[1] & Regs::CTRL1_SP_ENABLED_NO_CLIP) == Regs::CTRL1_SP_ENABLED_NO_CLIP ? 0xFF : 0x00;
- UpdatePalette();
- }
- void Ppu::UpdatePalette()
- {
- for (uint i=0, c=Coloring(), e=Emphasis(); i < Palette::SIZE; ++i)
- output.palette[i] = ((rgbMap ? rgbMap[palette.ram[i] & uint(Palette::COLOR)] : palette.ram[i]) & c) | e;
- }
- void Ppu::SaveState(State::Saver& state,const dword baseChunk) const
- {
- state.Begin( baseChunk );
- {
- const byte data[11] =
- {
- regs.ctrl[0],
- regs.ctrl[1],
- regs.status,
- scroll.address & 0xFF,
- scroll.address >> 8,
- scroll.latch & 0xFF,
- scroll.latch >> 8,
- scroll.xFine | scroll.toggle << 3,
- regs.oam,
- io.buffer,
- io.latch
- };
- state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
- }
- state.Begin( AsciiId<'P','A','L'>::V ).Compress( palette.ram ).End();
- state.Begin( AsciiId<'O','A','M'>::V ).Compress( oam.ram ).End();
- state.Begin( AsciiId<'N','M','T'>::V ).Compress( nameTable.ram ).End();
- if (model == PPU_RP2C02)
- state.Begin( AsciiId<'F','R','M'>::V ).Write8( (regs.frame & Regs::FRAME_ODD) == 0 ).End();
- if (cycles.hClock == HCLOCK_BOOT)
- state.Begin( AsciiId<'P','O','W'>::V ).Write8( 0x0 ).End();
- state.End();
- }
- void Ppu::LoadState(State::Loader& state)
- {
- cycles.hClock = HCLOCK_DUMMY;
- regs.frame = 0;
- output.burstPhase = 0;
- while (const dword chunk = state.Begin())
- {
- switch (chunk)
- {
- case AsciiId<'R','E','G'>::V:
- {
- State::Loader::Data<11> data( state );
- regs.ctrl[0] = data[0];
- regs.ctrl[1] = data[1];
- regs.status = data[2] & Regs::STATUS_BITS;
- scroll.address = data[3] | (data[4] << 8 & 0x7F00);
- scroll.latch = data[5] | (data[6] << 8 & 0x7F00);
- scroll.xFine = data[7] & 0x7;
- scroll.toggle = data[7] >> 3 & 0x1;
- regs.oam = data[8];
- io.buffer = data[9];
- io.latch = data[10];
- break;
- }
- case AsciiId<'P','A','L'>::V:
- state.Uncompress( palette.ram );
- break;
- case AsciiId<'O','A','M'>::V:
- state.Uncompress( oam.ram );
- break;
- case AsciiId<'N','M','T'>::V:
- state.Uncompress( nameTable.ram );
- break;
- case AsciiId<'F','R','M'>::V:
- if (model == PPU_RP2C02)
- regs.frame = (state.Read8() & 0x1) ? 0 : Regs::FRAME_ODD;
- break;
- case AsciiId<'P','O','W'>::V:
- cycles.hClock = HCLOCK_BOOT;
- break;
- }
- state.End();
- }
- UpdateStates();
- }
- void Ppu::EnableCpuSynchronization()
- {
- cpu.AddHook( Hook(this,&Ppu::Hook_Sync) );
- }
- void Ppu::ChrMem::ResetAccessor()
- {
- accessor.Set( this, &ChrMem::Access_Pattern );
- }
- void Ppu::NmtMem::ResetAccessors()
- {
- accessors[0].Set( this, &NmtMem::Access_Name_2000 );
- accessors[1].Set( this, &NmtMem::Access_Name_2400 );
- accessors[2].Set( this, &NmtMem::Access_Name_2800 );
- accessors[3].Set( this, &NmtMem::Access_Name_2C00 );
- }
- void Ppu::SetModel(const PpuModel m,const bool yuvConversion)
- {
- if (model != m)
- {
- model = m;
- regs.frame = 0;
- output.burstPhase = 0;
- switch (model)
- {
- case PPU_RP2C07: cycles.one = PPU_RP2C07_CC; break;
- case PPU_DENDY: cycles.one = PPU_DENDY_CC; break;
- default: cycles.one = PPU_RP2C02_CC; break;
- }
- }
- const byte* const map =
- (
- model == PPU_RP2C04_0001 ? yuvMaps[0] :
- model == PPU_RP2C04_0002 ? yuvMaps[1] :
- model == PPU_RP2C04_0003 ? yuvMaps[2] :
- model == PPU_RP2C04_0004 ? yuvMaps[3] :
- NULL
- );
- const byte* const tmp[2] =
- {
- yuvConversion ? NULL : map,
- yuvConversion ? map : NULL
- };
- if (yuvMap != tmp[0] || rgbMap != tmp[1])
- {
- yuvMap = tmp[0];
- rgbMap = tmp[1];
- UpdatePalette();
- }
- }
- #ifdef NST_MSVC_OPTIMIZE
- #pragma optimize("", on)
- #endif
- NST_FORCE_INLINE Cycle Ppu::GetCycles() const
- {
- return (cycles.vClock + cycles.hClock) * cycles.one;
- }
- NST_FORCE_INLINE Cycle Ppu::GetLocalCycles(Cycle clock) const
- {
- NST_COMPILE_ASSERT( PPU_DENDY_CC == PPU_RP2C02_CC || PPU_DENDY_CC == PPU_RP2C07_CC );
- return cycles.one == PPU_RP2C02_CC ? clock / PPU_RP2C02_CC : (clock+PPU_RP2C07_CC-1) / PPU_RP2C07_CC;
- }
- void Ppu::BeginFrame(bool frameLock)
- {
- NST_ASSERT
- (
- (scanline == SCANLINE_VBLANK) &&
- (cycles.hClock == HCLOCK_BOOT || cycles.hClock == HCLOCK_DUMMY) &&
- (cpu.GetModel() == CPU_RP2A07) == (model == PPU_RP2C07) &&
- (cpu.GetModel() == CPU_DENDY) == (model == PPU_DENDY)
- );
- oam.limit = oam.buffer + ((oam.spriteLimit || frameLock) ? Oam::STD_LINE_SPRITES*4 : Oam::MAX_LINE_SPRITES*4);
- output.target = output.pixels;
- Cycle frame;
- scanline_sleep = -1;
- switch (model)
- {
- case PPU_RP2C02:
- regs.frame ^= Regs::FRAME_ODD;
- default:
- ssleep = PPU_RP2C02_VSLEEP - 2;
- if (cycles.hClock == HCLOCK_DUMMY)
- {
- cycles.vClock = PPU_RP2C02_HVINT / PPU_RP2C02_CC - HCLOCK_DUMMY;
- cycles.count = PPU_RP2C02_HVINT;
- frame = PPU_RP2C02_HVSYNC_0;
- }
- else
- {
- cycles.vClock = PPU_RP2C02_HVSYNCBOOT / PPU_RP2C02_CC - HCLOCK_BOOT;
- cycles.count = PPU_RP2C02_HVSYNCBOOT;
- frame = PPU_RP2C02_HVSYNCBOOT;
- }
- break;
- case PPU_RP2C07:
- ssleep = PPU_RP2C07_VSLEEP - 2;
- if (cycles.hClock == HCLOCK_DUMMY)
- {
- cycles.vClock = PPU_RP2C07_HVINT / PPU_RP2C07_CC - HCLOCK_DUMMY;
- cycles.count = PPU_RP2C07_HVINT;
- frame = PPU_RP2C07_HVSYNC;
- }
- else
- {
- cycles.vClock = PPU_RP2C07_HVSYNCBOOT / PPU_RP2C07_CC - HCLOCK_BOOT;
- cycles.count = PPU_RP2C07_HVSYNCBOOT;
- frame = PPU_RP2C07_HVSYNCBOOT;
- }
- break;
- case PPU_DENDY:
- ssleep = PPU_DENDY_VSLEEP - 2;
- if (cycles.hClock == HCLOCK_DUMMY)
- {
- cycles.vClock = PPU_DENDY_HVINT / PPU_DENDY_CC - HCLOCK_DUMMY;
- cycles.count = PPU_DENDY_HVINT;
- frame = PPU_DENDY_HVSYNC;
- }
- else
- {
- cycles.vClock = PPU_DENDY_HVSYNCBOOT / PPU_DENDY_CC - HCLOCK_BOOT;
- cycles.count = PPU_DENDY_HVSYNCBOOT;
- frame = PPU_DENDY_HVSYNCBOOT;
- }
- break;
- }
- if (overclocked)
- {
- Apu& audioSafeOverclock = cpu.GetApu();
- if (audioSafeOverclock.GetOverclockSafety())
- {
- switch (model)
- {
- case PPU_RP2C02:
- default:
- cpu.SetOverclocking(true,PPU_RP2C02_HSYNC * PPU_RP2C02_VACTIVE);
- break;
- case PPU_RP2C07:
- cpu.SetOverclocking(true,PPU_RP2C07_HSYNC * PPU_RP2C07_VACTIVE);
- break;
- case PPU_DENDY:
- cpu.SetOverclocking(true,PPU_DENDY_HSYNC * PPU_DENDY_VACTIVE);
- break;
- }
- }
- else
- {
- cpu.SetOverclocking(false,0);
- }
- audioSafeOverclock.SetOverclockSafety(true);//overclocking is only safe if direct pcm audio has not been written for one frame
- }
- else
- {
- cpu.SetOverclocking(false,0);
- Apu& audioSafeOverclock = cpu.GetApu();
- audioSafeOverclock.SetOverclockSafety(false);
- }
- cpu.SetFrameCycles( frame );
- }
- NES_HOOK(Ppu,Sync)
- {
- const Cycle elapsed = cpu.GetCycles();
- if (cycles.count < elapsed)
- {
- cycles.count = GetLocalCycles( elapsed ) - cycles.vClock;
- Run();
- }
- }
- void Ppu::EndFrame()
- {
- if (cycles.count != Cpu::CYCLE_MAX)
- {
- cycles.count = Cpu::CYCLE_MAX;
- Run();
- }
- }
- void Ppu::Update(Cycle dataSetup,const uint readAddress)
- {
- dataSetup += cpu.Update( readAddress );
- if (cycles.count < dataSetup)
- {
- cycles.count = GetLocalCycles( dataSetup ) - cycles.vClock;
- Run();
- }
- }
- void Ppu::SetMirroring(const byte (&banks)[4])
- {
- Update( cycles.one );
- NST_ASSERT( banks[0] < 4 && banks[1] < 4 && banks[2] < 4 && banks[3] < 4 );
- nmt.SwapBanks<SIZE_1K,0x0000>( banks[0], banks[1], banks[2], banks[3] );
- }
- void Ppu::SetMirroring(NmtMirroring mirroring)
- {
- Update( cycles.one );
- nmt.SwapBanks<SIZE_1K,0x0000>
- (
- uint(mirroring) >> 0 & 0x1U,
- uint(mirroring) >> 1 & 0x1U,
- uint(mirroring) >> 2 & 0x1U,
- uint(mirroring) >> 3 & 0x1U
- );
- }
- NES_ACCESSOR(Ppu::ChrMem,Pattern)
- {
- return Peek( address );
- }
- NES_ACCESSOR(Ppu::NmtMem,Name_2000)
- {
- return (*this)[0][address];
- }
- NES_ACCESSOR(Ppu::NmtMem,Name_2400)
- {
- return (*this)[1][address];
- }
- NES_ACCESSOR(Ppu::NmtMem,Name_2800)
- {
- return (*this)[2][address];
- }
- NES_ACCESSOR(Ppu::NmtMem,Name_2C00)
- {
- return (*this)[3][address];
- }
- NST_FORCE_INLINE uint Ppu::Chr::FetchPattern(uint address) const
- {
- return accessor.Fetch( address & 0x1FFF );
- }
- NST_FORCE_INLINE uint Ppu::Nmt::FetchName(uint address) const
- {
- return accessors[address >> 10 & 0x3].Fetch( address & 0x3FF );
- }
- NST_FORCE_INLINE uint Ppu::Nmt::FetchAttribute(uint address) const
- {
- return accessors[address >> 10 & 0x3].Fetch( 0x3C0 | (address & 0x03F) );
- }
- NST_FORCE_INLINE void Ppu::UpdateAddressLine(uint address)
- {
- NST_ASSERT( address <= 0x3FFF );
- io.address = address;
- if (io.line)
- io.line.Toggle( io.address, GetCycles() );
- }
- NST_FORCE_INLINE void Ppu::UpdateVramAddress()
- {
- if ((scanline != SCANLINE_VBLANK ) && (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED))
- {
- scroll.ClockX();
- scroll.ClockY();
- }
- else
- {
- scroll.address = (scroll.address + ((regs.ctrl[0] & Regs::CTRL0_INC32) ? 32 : 1)) & 0x7FFF;
- }
- }
- NST_FORCE_INLINE void Ppu::OpenName()
- {
- UpdateAddressLine( 0x2000 | (scroll.address & 0x0FFF) );
- }
- NST_FORCE_INLINE void Ppu::FetchName()
- {
- io.pattern = nmt.FetchName( io.address ) << 4 | scroll.address >> 12 | (regs.ctrl[0] << 8 & 0x1000);
- }
- NST_FORCE_INLINE void Ppu::OpenAttribute()
- {
- UpdateAddressLine( 0x23C0 | (scroll.address & 0x0C00) | (scroll.address >> 4 & 0x0038) | (scroll.address >> 2 & 0x0007) );
- }
- NST_FORCE_INLINE void Ppu::FetchAttribute()
- {
- tiles.attribute = nmt.FetchAttribute( io.address ) >> ((scroll.address & 0x2) | (scroll.address >> 4 & 0x4));
- }
- NST_FORCE_INLINE void Ppu::OpenPattern(uint address)
- {
- UpdateAddressLine( address );
- }
- NST_FORCE_INLINE uint Ppu::FetchSpPattern() const
- {
- return chr.FetchPattern( io.address );
- }
- NST_FORCE_INLINE void Ppu::FetchBgPattern0()
- {
- const uint pattern = chr.FetchPattern( io.address );
- tiles.pattern[1] = pattern >> 0 & 0x55;
- tiles.pattern[0] = pattern >> 1 & 0x55;
- }
- NST_FORCE_INLINE void Ppu::FetchBgPattern1()
- {
- const uint pattern = chr.FetchPattern( io.address );
- tiles.pattern[0] |= pattern << 0 & 0xAA;
- tiles.pattern[1] |= pattern << 1 & 0xAA;
- }
- uint Ppu::GetPixelCycles() const
- {
- return (scanline+1)-1U < 240 ? scanline * 256 + NST_MIN(cycles.hClock,255) : ~0U;
- }
- NST_FORCE_INLINE bool Ppu::IsDead() const
- {
- return scanline == SCANLINE_VBLANK || !(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED);
- }
- NST_FORCE_INLINE uint Ppu::Coloring() const
- {
- return (regs.ctrl[1] & Regs::CTRL1_MONOCHROME) ? Palette::MONO : Palette::COLOR;
- }
- NST_FORCE_INLINE uint Ppu::Emphasis() const
- {
- return (regs.ctrl[1] & Regs::CTRL1_EMPHASIS) << 1;
- }
- NES_POKE_D(Ppu,2000)
- {
- Update( cycles.one );
- NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
- if (cpu.GetCycles() >= cycles.reset)
- {
- scroll.latch = (scroll.latch & 0x73FF) | (data & 0x03) << 10;
- oam.height = (data >> 2 & 8) + 8;
- io.latch = data;
- data = regs.ctrl[0] ;
- regs.ctrl[0] = io.latch;
- if ((regs.ctrl[0] & regs.status & Regs::CTRL0_NMI) > data)
- {
- const Cycle clock = cpu.GetCycles() + cycles.one;
- if (clock < GetHVIntClock())
- cpu.DoNMI( clock );
- }
- }
- }
- NES_POKE_D(Ppu,2001)
- {
- Update( cycles.one );
- NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
- if (cpu.GetCycles() >= cycles.reset)
- {
- if ((regs.ctrl[1] ^ data) & (Regs::CTRL1_BG_ENABLED_NO_CLIP|Regs::CTRL1_SP_ENABLED_NO_CLIP))
- {
- tiles.show[0] = (data & Regs::CTRL1_BG_ENABLED) ? 0xFF : 0x00;
- tiles.show[1] = (data & Regs::CTRL1_BG_ENABLED_NO_CLIP) == Regs::CTRL1_BG_ENABLED_NO_CLIP ? 0xFF : 0x00;
- oam.show[0] = (data & Regs::CTRL1_SP_ENABLED) ? 0xFF : 0x00;
- oam.show[1] = (data & Regs::CTRL1_SP_ENABLED_NO_CLIP) == Regs::CTRL1_SP_ENABLED_NO_CLIP ? 0xFF : 0x00;
- const uint pos = (cycles.hClock - 8) >= (256-16);
- tiles.mask = tiles.show[pos];
- oam.mask = oam.show[pos];
- if ((regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) && !(data & Regs::CTRL1_BG_SP_ENABLED))
- UpdateAddressLine(scroll.address & 0x3fff);
- }
- io.latch = data;
- data = (regs.ctrl[1] ^ data) & (Regs::CTRL1_EMPHASIS|Regs::CTRL1_MONOCHROME);
- regs.ctrl[1] = io.latch;
- if (data)
- {
- const uint ce[] = { Coloring(), Emphasis() };
- const byte* const NST_RESTRICT map = rgbMap;
- if (!map)
- {
- for (uint i=0; i < Palette::SIZE; ++i)
- output.palette[i] = (palette.ram[i] & ce[0]) | ce[1];
- }
- else
- {
- for (uint i=0; i < Palette::SIZE; ++i)
- output.palette[i] = (map[palette.ram[i] & Palette::COLOR] & ce[0]) | ce[1];
- }
- }
- }
- }
- NES_PEEK_A(Ppu,2002)
- {
- Update( cycles.one, address );
- uint status = regs.status & 0xFF;
- regs.status &= (Regs::STATUS_VBLANK^0xFFU);
- scroll.toggle = 0;
- io.latch = (io.latch & Regs::STATUS_LATCH) | status;
- return io.latch;
- }
- NES_PEEK_A(Ppu,2002_RC2C05_01_04)
- {
- return (NES_DO_PEEK(2002,address) & 0xC0) | 0x1B;
- }
- NES_PEEK_A(Ppu,2002_RC2C05_02)
- {
- return (NES_DO_PEEK(2002,address) & 0xC0) | 0x3D;
- }
- NES_PEEK_A(Ppu,2002_RC2C05_03)
- {
- return (NES_DO_PEEK(2002,address) & 0xC0) | 0x1C;
- }
- NES_POKE_D(Ppu,2003)
- {
- Update( cycles.one );
- regs.oam = data;
- io.latch = data;
- }
- NES_POKE_D(Ppu,2004)
- {
- Update( cycles.one );
- NST_ASSERT( regs.oam < Oam::SIZE );
- NST_VERIFY( IsDead() );
- if (IsDead())
- {
- if ((regs.oam & 0x03) == 0x02)
- data &= 0xE3;
- }
- else
- {
- data = 0xFF;
- }
- byte* const NST_RESTRICT value = oam.ram + regs.oam;
- regs.oam = (regs.oam + 1) & 0xFF;
- io.latch = data;
- *value = data;
- }
- NES_PEEK(Ppu,2004)
- {
- NST_ASSERT( regs.oam <= 0xFF );
- if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() - (cpu.GetFrameCycles() - (341 * 241) * cycles.one) >= (341 * 240) * cycles.one)
- {
- io.latch = oam.ram[regs.oam];
- }
- else
- {
- Update( cycles.one );
- io.latch = oam.latch;
- }
- return io.latch;
- }
- NES_POKE_D(Ppu,2005)
- {
- Update( cycles.one );
- NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
- if (cpu.GetCycles() >= cycles.reset)
- {
- io.latch = data;
- if (scroll.toggle ^= 1)
- {
- scroll.latch = (scroll.latch & 0x7FE0) | (data >> 3);
- scroll.xFine = data & 0x7;
- }
- else
- {
- scroll.latch = (scroll.latch & 0x0C1F) | ((data << 2 | data << 12) & 0x73E0);
- }
- }
- }
- NES_POKE_D(Ppu,2006)
- {
- Update( cycles.one );
- NST_VERIFY( cpu.GetCycles() >= cycles.reset || !data );
- if (cpu.GetCycles() >= cycles.reset)
- {
- io.latch = data;
- if (scroll.toggle ^= 1)
- {
- scroll.latch = (scroll.latch & 0x00FF) | (data & 0x3F) << 8;
- }
- else
- {
- scroll.latch = (scroll.latch & 0x7F00) | data;
- scroll.address = scroll.latch;
- if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
- (scanline == SCANLINE_VBLANK)) {
- UpdateAddressLine(scroll.address & 0x3fff);
- }
- }
- }
- }
- NES_POKE_D(Ppu,2007)
- {
- Update( cycles.one * 4 );
- uint address = scroll.address;
- UpdateVramAddress();
- if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
- (scanline == SCANLINE_VBLANK)) {
- UpdateAddressLine(scroll.address & 0x3fff);
- }
- else {
- return;
- }
- io.latch = data;
- if ((address & 0x3F00) == 0x3F00)
- {
- address &= 0x1F;
- const uint final = ((!rgbMap ? data : rgbMap[data & Palette::COLOR]) & Coloring()) | Emphasis();
- palette.ram[address] = data;
- output.palette[address] = final;
- if (!(address & 0x3))
- {
- palette.ram[address ^ 0x10] = data;
- output.palette[address ^ 0x10] = final;
- }
-
- output.bgColor = palette.ram[0] & uint(Palette::COLOR);
- }
- else
- {
- address &= 0x3FFF;
- if (address >= 0x2000)
- nmt.Poke( address & 0xFFF, data );
- else
- chr.Poke( address, data );
- }
- }
- NES_PEEK_A(Ppu,2007)
- {
- Update( cycles.one, address );
- address = scroll.address & 0x3FFF;
- UpdateVramAddress();
- if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
- (scanline == SCANLINE_VBLANK)) {
- UpdateAddressLine(scroll.address & 0x3fff);
- }
- io.latch = (address & 0x3F00) != 0x3F00 ? io.buffer : palette.ram[address & 0x1F] & Coloring();
- io.buffer = (address >= 0x2000 ? nmt.FetchName( address ) : chr.FetchPattern( address ));
- return io.latch;
- }
- NES_POKE_D(Ppu,2xxx)
- {
- io.latch = data;
- }
- NES_PEEK(Ppu,2xxx)
- {
- return io.latch;
- }
- NES_PEEK(Ppu,3000)
- {
- Update( cycles.one );
- return io.latch;
- }
- NES_POKE_D(Ppu,4014)
- {
- if (cpu.IsOddCycle())
- cpu.StealCycles( cpu.GetClock() );
- Update( cycles.one );
- cpu.StealCycles( cpu.GetClock() );
- NST_ASSERT( regs.oam < 0x100 );
- data <<= 8;
- if ((regs.oam == 0x00 && data < 0x2000) && (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() <= GetHVIntClock() - cpu.GetClock() * 512))
- {
- cpu.StealCycles( cpu.GetClock() * 512 );
- const byte* const NST_RESTRICT cpuRam = cpu.GetRam() + (data & (Cpu::RAM_SIZE-1));
- byte* const NST_RESTRICT oamRam = oam.ram;
- for (uint i=0x00; i < 0x100; i += 0x4)
- {
- oamRam[i+0x0] = cpuRam[i+0x0];
- oamRam[i+0x1] = cpuRam[i+0x1];
- oamRam[i+0x2] = cpuRam[i+0x2] & 0xE3U;
- oamRam[i+0x3] = cpuRam[i+0x3];
- }
- io.latch = oamRam[0xFF];
- }
- else do
- {
- io.latch = cpu.Peek( data++ );
- cpu.StealCycles( cpu.GetClock() );
- Update( cycles.one );
- cpu.StealCycles( cpu.GetClock() );
- NST_VERIFY( IsDead() );
- if (IsDead())
- {
- if ((regs.oam & 0x03) == 0x02)
- io.latch &= 0xE3;
- }
- else
- {
- io.latch = 0xFF;
- }
- byte* const NST_RESTRICT out = oam.ram + regs.oam;
- regs.oam = (regs.oam + 1) & 0xFF;
- *out = io.latch;
- }
- while (data & 0xFF);
- }
- NES_PEEK(Ppu,4014)
- {
- return 0x40;
- }
- NST_FORCE_INLINE void Ppu::Scroll::ClockX()
- {
- if ((address & X_TILE) != X_TILE)
- address++;
- else
- address ^= (X_TILE|NAME_LOW);
- }
- NST_SINGLE_CALL void Ppu::Scroll::ResetX()
- {
- address = (address & ((X_TILE|NAME_LOW) ^ 0x7FFFU)) | (latch & (X_TILE|NAME_LOW));
- }
- NST_SINGLE_CALL void Ppu::Scroll::ClockY()
- {
- if ((address & Y_FINE) != (7U << 12))
- {
- address += (1U << 12);
- }
- else switch (address & Y_TILE)
- {
- default: address = (address & (Y_FINE ^ 0x7FFFU)) + (1U << 5); break;
- case (29U << 5): address ^= NAME_HIGH;
- case (31U << 5): address &= (Y_FINE|Y_TILE) ^ 0x7FFFU; break;
- }
- }
- NST_SINGLE_CALL void Ppu::PreLoadTiles()
- {
- const byte* const NST_RESTRICT src[] =
- {
- tileLut.block[tiles.pattern[0] | (tiles.attribute & 0x3U) << 8],
- tileLut.block[tiles.pattern[1] | (tiles.attribute & 0x3U) << 8]
- };
- NST_ASSERT( tiles.index == 8 );
- byte* const NST_RESTRICT dst = tiles.pixels;
- dst[0] = src[0][0];
- dst[1] = src[1][0];
- dst[2] = src[0][1];
- dst[3] = src[1][1];
- dst[4] = src[0][2];
- dst[5] = src[1][2];
- dst[6] = src[0][3];
- dst[7] = src[1][3];
- }
- NST_SINGLE_CALL void Ppu::LoadTiles()
- {
- const byte* const NST_RESTRICT src[] =
- {
- tileLut.block[tiles.pattern[0] | (tiles.attribute & 0x3U) << 8],
- tileLut.block[tiles.pattern[1] | (tiles.attribute & 0x3U) << 8]
- };
- NST_ASSERT( tiles.index == 0 || tiles.index == 8 );
- byte* const NST_RESTRICT dst = tiles.pixels + tiles.index;
- tiles.index ^= 8U;
- dst[0] = src[0][0];
- dst[1] = src[1][0];
- dst[2] = src[0][1];
- dst[3] = src[1][1];
- dst[4] = src[0][2];
- dst[5] = src[1][2];
- dst[6] = src[0][3];
- dst[7] = src[1][3];
- }
- NST_FORCE_INLINE void Ppu::EvaluateSpritesEven()
- {
- if (cycles.hClock >= 64)
- oam.latch = oam.ram[oam.address];
- }
- NST_FORCE_INLINE void Ppu::EvaluateSpritesOdd()
- {
- (*this.*oam.phase)();
- }
- void Ppu::EvaluateSpritesPhase0()
- {
- }
- void Ppu::EvaluateSpritesPhase1()
- {
- oam.index++;
- if (scanline - oam.latch >= oam.height)
- {
- if (oam.index != 64)
- {
- oam.address = (oam.index != 2 ? oam.address + 4 : 8);
- }
- else
- {
- oam.address = 0;
- oam.phase = &Ppu::EvaluateSpritesPhase9;
- }
- }
- else
- {
- oam.address++;
- oam.phase = &Ppu::EvaluateSpritesPhase2;
- oam.buffered[0] = oam.latch;
- }
- }
- void Ppu::EvaluateSpritesPhase2()
- {
- oam.address++;
- oam.phase = &Ppu::EvaluateSpritesPhase3;
- oam.buffered[1] = oam.latch;
- }
- void Ppu::EvaluateSpritesPhase3()
- {
- oam.address++;
- oam.phase = &Ppu::EvaluateSpritesPhase4;
- oam.buffered[2] = oam.latch;
- }
- void Ppu::EvaluateSpritesPhase4()
- {
- oam.buffered[3] = oam.latch;
- oam.buffered += 4;
- if (oam.index != 64)
- {
- oam.phase = (oam.buffered != oam.limit ? &Ppu::EvaluateSpritesPhase1 : &Ppu::EvaluateSpritesPhase5);
- if (oam.index != 2)
- {
- oam.address++;
- if (oam.index == 1)
- oam.spriteZeroInLine = true;
- }
- else
- {
- oam.address = 8;
- }
- }
- else
- {
- oam.address = 0;
- oam.phase = &Ppu::EvaluateSpritesPhase9;
- }
- }
- void Ppu::EvaluateSpritesPhase5()
- {
- if (scanline - oam.latch >= oam.height)
- {
- oam.address = ((oam.address + 4) & 0xFC) + ((oam.address + 1) & 0x03);
- if (oam.address <= 5)
- {
- oam.phase = &Ppu::EvaluateSpritesPhase9;
- oam.address &= 0xFC;
- }
- }
- else
- {
- oam.phase = &Ppu::EvaluateSpritesPhase6;
- oam.address = (oam.address + 1) & 0xFF;
- regs.status |= Regs::STATUS_SP_OVERFLOW;
- }
- }
- void Ppu::EvaluateSpritesPhase6()
- {
- oam.phase = &Ppu::EvaluateSpritesPhase7;
- oam.address = (oam.address + 1) & 0xFF;
- }
- void Ppu::EvaluateSpritesPhase7()
- {
- oam.phase = &Ppu::EvaluateSpritesPhase8;
- oam.address = (oam.address + 1) & 0xFF;
- }
- void Ppu::EvaluateSpritesPhase8()
- {
- oam.phase = &Ppu::EvaluateSpritesPhase9;
- oam.address = (oam.address + 1) & 0xFF;
- if ((oam.address & 0x3) == 0x3)
- oam.address++;
- oam.address &= 0xFC;
- }
- void Ppu::EvaluateSpritesPhase9()
- {
- oam.address = (oam.address + 4) & 0xFF;
- }
- NST_FORCE_INLINE uint Ppu::OpenSprite() const
- {
- return (regs.ctrl[0] & (Regs::CTRL0_SP_OFFSET|Regs::CTRL0_SP8X16)) ? 0x1FF0 : 0x0FF0;
- }
- NST_FORCE_INLINE uint Ppu::OpenSprite(const byte* const NST_RESTRICT buffer) const
- {
- uint address;
- const uint comparitor = (uint(scanline) - buffer[0]) ^ ((buffer[2] & uint(Oam::Y_FLIP)) ? 0xF : 0x0);
- if (regs.ctrl[0] & Regs::CTRL0_SP8X16)
- {
- address =
- (
- ((buffer[1] & uint(Oam::TILE_LSB)) << 12) |
- ((buffer[1] & (Oam::TILE_LSB ^ 0xFFU)) << 4) |
- ((comparitor & Oam::RANGE_MSB) << 1)
- );
- }
- else
- {
- address = (regs.ctrl[0] & Regs::CTRL0_SP_OFFSET) << 9 | buffer[1] << 4;
- }
- return address | (comparitor & Oam::XFINE);
- }
- NST_FORCE_INLINE void Ppu::LoadSprite(const uint pattern0,const uint pattern1,const byte* const NST_RESTRICT buffer)
- {
- if (pattern0 | pattern1)
- {
- uint a = (buffer[2] & uint(Oam::X_FLIP)) ? 7 : 0;
- uint p =
- (
- (pattern0 >> 1 & 0x0055) | (pattern1 << 0 & 0x00AA) |
- (pattern0 << 8 & 0x5500) | (pattern1 << 9 & 0xAA00)
- );
- Oam::Output* const NST_RESTRICT entry = oam.visible++;
- entry->pixels[( a^=6 )] = ( p ) & 0x3;
- entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=6 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=7 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=2 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=6 )] = ( p >>= 2 ) & 0x3;
- entry->pixels[( a^=2 )] = ( p >>= 2 );
- const uint attribute = buffer[2];
- entry->x = buffer[3];
- entry->palette = Palette::SPRITE_OFFSET + ((attribute & Oam::COLOR) << 2);
- entry->behind = (attribute & Oam::BEHIND) ? 0x3 : 0x0;
- entry->zero = (buffer == oam.buffer && oam.spriteZeroInLine) ? 0x3 : 0x0;
- }
- }
- void Ppu::LoadExtendedSprites()
- {
- const byte* NST_RESTRICT buffer = oam.buffer + (8*4);
- NST_ASSERT( buffer < oam.buffered );
- do
- {
- const uint address = OpenSprite( buffer );
- const uint patterns[2] =
- {
- chr.FetchPattern( address | 0x0 ),
- chr.FetchPattern( address | 0x8 )
- };
- LoadSprite( patterns[0], patterns[1], buffer );
- buffer += 4;
- }
- while (buffer != oam.buffered);
- }
- NST_FORCE_INLINE void Ppu::RenderPixel()
- {
- uint clock;
- uint pixel = tiles.pixels[((clock=cycles.hClock++) + scroll.xFine) & 15] & tiles.mask;
- for (const Oam::Output* NST_RESTRICT sprite=oam.output, *const end=oam.visible; sprite != end; ++sprite)
- {
- uint x = clock - sprite->x;
- if (x > 7)
- continue;
- x = sprite->pixels[x] & oam.mask;
- if (x)
- {
- if (pixel & sprite->zero)
- regs.status |= Regs::STATUS_SP_ZERO_HIT;
- if (!(pixel & sprite->behind))
- pixel = sprite->palette + x;
- break;
- }
- }
- Video::Screen::Pixel* const NST_RESTRICT target = output.target++;
- *target = output.palette[pixel];
- }
- NST_SINGLE_CALL void Ppu::RenderPixel255()
- {
- cycles.hClock = 256;
- uint pixel = tiles.pixels[(255 + scroll.xFine) & 15] & tiles.mask;
- for (const Oam::Output* NST_RESTRICT sprite=oam.output, *const end=oam.visible; sprite != end; ++sprite)
- {
- uint x = 255U - sprite->x;
- if (x > 7)
- continue;
- x = sprite->pixels[x] & oam.mask;
- if (x)
- {
- if (!(pixel & sprite->behind))
- pixel = sprite->palette + x;
- break;
- }
- }
- Video::Screen::Pixel* const NST_RESTRICT target = output.target++;
- *target = output.palette[pixel];
- }
- NST_NO_INLINE void Ppu::Run()
- {
- NST_VERIFY( cycles.count != cycles.hClock );
- if (scanline_sleep >= 0)
- {
- switch (cycles.hClock)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- case 20:
- case 21:
- case 22:
- case 23:
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- case 38:
- case 39:
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- case 48:
- case 49:
- case 50:
- case 51:
- case 52:
- case 53:
- case 54:
- case 55:
- case 56:
- case 57:
- case 58:
- case 59:
- case 60:
- case 61:
- case 62:
- case 63:
- case 64:
- case 65:
- case 66:
- case 67:
- case 68:
- case 69:
- case 70:
- case 71:
- case 72:
- case 73:
- case 74:
- case 75:
- case 76:
- case 77:
- case 78:
- case 79:
- case 80:
- case 81:
- case 82:
- case 83:
- case 84:
- case 85:
- case 86:
- case 87:
- case 88:
- case 89:
- case 90:
- case 91:
- case 92:
- case 93:
- case 94:
- case 95:
- case 96:
- case 97:
- case 98:
- case 99:
- case 100:
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- case 107:
- case 108:
- case 109:
- case 110:
- case 111:
- case 112:
- case 113:
- case 114:
- case 115:
- case 116:
- case 117:
- case 118:
- case 119:
- case 120:
- case 121:
- case 122:
- case 123:
- case 124:
- case 125:
- case 126:
- case 127:
- case 128:
- case 129:
- case 130:
- case 131:
- case 132:
- case 133:
- case 134:
- case 135:
- case 136:
- case 137:
- case 138:
- case 139:
- case 140:
- case 141:
- case 142:
- case 143:
- case 144:
- case 145:
- case 146:
- case 147:
- case 148:
- case 149:
- case 150:
- case 151:
- case 152:
- case 153:
- case 154:
- case 155:
- case 156:
- case 157:
- case 158:
- case 159:
- case 160:
- case 161:
- case 162:
- case 163:
- case 164:
- case 165:
- case 166:
- case 167:
- case 168:
- case 169:
- case 170:
- case 171:
- case 172:
- case 173:
- case 174:
- case 175:
- case 176:
- case 177:
- case 178:
- case 179:
- case 180:
- case 181:
- case 182:
- case 183:
- case 184:
- case 185:
- case 186:
- case 187:
- case 188:
- case 189:
- case 190:
- case 191:
- case 192:
- case 193:
- case 194:
- case 195:
- case 196:
- case 197:
- case 198:
- case 199:
- case 200:
- case 201:
- case 202:
- case 203:
- case 204:
- case 205:
- case 206:
- case 207:
- case 208:
- case 209:
- case 210:
- case 211:
- case 212:
- case 213:
- case 214:
- case 215:
- case 216:
- case 217:
- case 218:
- case 219:
- case 220:
- case 221:
- case 222:
- case 223:
- case 224:
- case 225:
- case 226:
- case 227:
- case 228:
- case 229:
- case 230:
- case 231:
- case 232:
- case 233:
- case 234:
- case 235:
- case 236:
- case 237:
- case 238:
- case 239:
- case 240:
- case 241:
- case 242:
- case 243:
- case 244:
- case 245:
- case 246:
- case 247:
- case 248:
- case 249:
- case 250:
- case 251:
- case 252:
- case 253:
- case 254:
- case 255:
- case 256:
- case 257:
- case 258:
- case 260:
- case 261:
- case 262:
- case 263:
- case 264:
- case 266:
- case 267:
- case 268:
- case 269:
- case 270:
- case 271:
- case 272:
- case 273:
- case 274:
- case 275:
- case 276:
- case 277:
- case 278:
- case 279:
- case 280:
- case 281:
- case 282:
- case 283:
- case 284:
- case 285:
- case 286:
- case 287:
- case 288:
- case 289:
- case 290:
- case 291:
- case 292:
- case 293:
- case 294:
- case 295:
- case 296:
- case 297:
- case 298:
- case 299:
- case 300:
- case 301:
- case 302:
- case 303:
- case 304:
- case 305:
- case 306:
- case 307:
- case 308:
- case 309:
- case 310:
- case 311:
- case 312:
- case 313:
- case 314:
- case 315:
- case 316:
- case 317:
- case 318:
- case 319:
- case 320:
- case 321:
- case 322:
- case 323:
- case 324:
- case 325:
- case 326:
- case 327:
- case 328:
- case 329:
- case 330:
- case 331:
- case 332:
- case 333:
- case 334:
- case 335:
- case 336:
- case 337:
- HActiveSleep:
- cycles.hClock = 338;
- if (cycles.count <= 338)
- break;
- case 338:
- if (scanline_sleep++ != ssleep)
- {
- cycles.hClock = 0;
- cycles.vClock += 341;
- if (cycles.count <= 341)
- break;
- cycles.count -= 341;
- goto HActiveSleep;
- }
- else
- {
- cycles.hClock = HCLOCK_VBLANK_0;
- if (cycles.count <= HCLOCK_VBLANK_0)
- break;
- }
- case HCLOCK_VBLANK_0:
- VBlank0:
- regs.status |= Regs::STATUS_VBLANKING;
- cycles.hClock = HCLOCK_VBLANK_1;
- if (cycles.count <= HCLOCK_VBLANK_1)
- break;
- case HCLOCK_VBLANK_1:
- VBlank1:
- regs.status = (regs.status & 0xFF) | (regs.status >> 1 & Regs::STATUS_VBLANK);
- oam.visible = oam.output;
- cycles.hClock = HCLOCK_VBLANK_2;
- if (cycles.count <= HCLOCK_VBLANK_2)
- break;
- case HCLOCK_VBLANK_2:
- VBlank2:
- scanline_sleep = -1;
- cycles.hClock = HCLOCK_DUMMY;
- cycles.count = Cpu::CYCLE_MAX;
- cycles.reset = 0;
- if (regs.ctrl[0] & regs.status & Regs::CTRL0_NMI)
- cpu.DoNMI( cpu.GetFrameCycles() );
- return;
- }
- }
- else if (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED)
- {
- switch (cycles.hClock)
- {
- case 0:
- case 8:
- case 16:
- case 24:
- case 32:
- case 40:
- case 48:
- case 56:
- case 72:
- case 80:
- case 88:
- case 96:
- case 104:
- case 112:
- case 120:
- case 128:
- case 136:
- case 144:
- case 152:
- case 160:
- case 168:
- case 176:
- case 184:
- case 192:
- case 200:
- case 208:
- case 216:
- case 224:
- case 232:
- case 240:
- case 248:
- HActive:
- LoadTiles();
- EvaluateSpritesEven();
- OpenName();
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 1:
- case 9:
- case 17:
- case 25:
- case 33:
- case 41:
- case 49:
- case 57:
- case 65:
- case 73:
- case 81:
- case 89:
- case 97:
- case 105:
- case 113:
- case 121:
- case 129:
- case 137:
- case 145:
- case 153:
- case 161:
- case 169:
- case 177:
- case 185:
- case 193:
- case 201:
- case 209:
- case 217:
- case 225:
- case 233:
- case 241:
- case 249:
- FetchName();
- EvaluateSpritesOdd();
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 2:
- case 10:
- case 18:
- case 26:
- case 34:
- case 42:
- case 50:
- case 58:
- case 66:
- case 74:
- case 82:
- case 90:
- case 98:
- case 106:
- case 114:
- case 122:
- case 130:
- case 138:
- case 146:
- case 154:
- case 162:
- case 170:
- case 178:
- case 186:
- case 194:
- case 202:
- case 210:
- case 218:
- case 226:
- case 234:
- case 242:
- case 250:
- EvaluateSpritesEven();
- OpenAttribute();
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 3:
- case 11:
- case 19:
- case 27:
- case 35:
- case 43:
- case 51:
- case 59:
- case 67:
- case 75:
- case 83:
- case 91:
- case 99:
- case 107:
- case 115:
- case 123:
- case 131:
- case 139:
- case 147:
- case 155:
- case 163:
- case 171:
- case 179:
- case 187:
- case 195:
- case 203:
- case 211:
- case 219:
- case 227:
- case 235:
- case 243:
- case 251:
- FetchAttribute();
- EvaluateSpritesOdd();
- if (cycles.hClock == 251)
- scroll.ClockY();
- scroll.ClockX();
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 4:
- case 12:
- case 20:
- case 28:
- case 36:
- case 44:
- case 52:
- case 60:
- case 68:
- case 76:
- case 84:
- case 92:
- case 100:
- case 108:
- case 116:
- case 124:
- case 132:
- case 140:
- case 148:
- case 156:
- case 164:
- case 172:
- case 180:
- case 188:
- case 196:
- case 204:
- case 212:
- case 220:
- case 228:
- case 236:
- case 244:
- case 252:
- EvaluateSpritesEven();
- OpenPattern( io.pattern | 0x0 );
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 5:
- case 13:
- case 21:
- case 29:
- case 37:
- case 45:
- case 53:
- case 61:
- case 69:
- case 77:
- case 85:
- case 93:
- case 101:
- case 109:
- case 117:
- case 125:
- case 133:
- case 141:
- case 149:
- case 157:
- case 165:
- case 173:
- case 181:
- case 189:
- case 197:
- case 205:
- case 213:
- case 221:
- case 229:
- case 237:
- case 245:
- case 253:
- FetchBgPattern0();
- EvaluateSpritesOdd();
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- case 6:
- case 14:
- case 22:
- case 30:
- case 38:
- case 46:
- case 54:
- case 62:
- case 70:
- case 78:
- case 86:
- case 94:
- case 102:
- case 110:
- case 118:
- case 126:
- case 134:
- case 142:
- case 150:
- case 158:
- case 166:
- case 174:
- case 182:
- case 190:
- case 198:
- case 206:
- case 214:
- case 222:
- case 230:
- case 238:
- case 246:
- case 254:
- EvaluateSpritesEven();
- OpenPattern( io.pattern | 0x8 );
- RenderPixel();
- if (cycles.count <= cycles.hClock)
- break;
- if (cycles.hClock == 255)
- goto HActive255;
- case 7:
- case 15:
- case 23:
- case 31:
- case 39:
- case 47:
- case 55:
- case 63:
- case 71:
- case 79:
- case 87:
- case 95:
- case 103:
- case 111:
- case 119:
- case 127:
- case 135:
- case 143:
- case 151:
- case 159:
- case 167:
- case 175:
- case 183:
- case 191:
- case 199:
- case 207:
- case 215:
- case 223:
- case 231:
- case 239:
- case 247:
- FetchBgPattern1();
- EvaluateSpritesOdd();
- RenderPixel();
- tiles.mask = tiles.show[0];
- oam.mask = oam.show[0];
- if (cycles.count <= cycles.hClock)
- break;
- if (cycles.hClock != 64)
- goto HActive;
- case 64:
- NST_VERIFY( regs.oam == 0 );
- oam.address = regs.oam & Oam::OFFSET_TO_0_1;
- oam.phase = &Ppu::EvaluateSpritesPhase1;
- oam.latch = 0xFF;
- goto HActive;
- case 255:
- HActive255:
- FetchBgPattern1();
- EvaluateSpritesOdd();
- RenderPixel255();
- if (cycles.count <= 256)
- break;
- case 256:
- OpenName();
- oam.latch = 0xFF;
- cycles.hClock = 257;
- if (cycles.count <= 257)
- break;
- case 257:
- if (hBlankHook)
- hBlankHook.Execute();
- scroll.ResetX();
- oam.visible = oam.output;
- cycles.hClock = 258;
- if (cycles.count <= 258)
- break;
- case 258:
- case 266:
- case 274:
- case 282:
- case 290:
- case 298:
- case 306:
- case 314:
- HBlankSp:
- OpenName();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case 260:
- case 268:
- case 276:
- case 284:
- case 292:
- case 300:
- case 308:
- case 316:
- {
- const byte* const buffer = oam.buffer + ((cycles.hClock - 260) / 2);
- OpenPattern( buffer >= oam.buffered ? OpenSprite() : OpenSprite(buffer) );
- if (scanline == 238 && cycles.hClock == 316)
- regs.oam = 0;
- if (cycles.count <= ++cycles.hClock)
- break;
- }
- case 261:
- case 269:
- case 277:
- case 285:
- case 293:
- case 301:
- case 309:
- case 317:
- if (oam.buffer + ((cycles.hClock - 261) / 2) < oam.buffered)
- io.pattern = FetchSpPattern();
- if (cycles.count <= ++cycles.hClock)
- break;
- case 262:
- case 270:
- case 278:
- case 286:
- case 294:
- case 302:
- case 310:
- case 318:
- OpenPattern( io.address | 0x8 );
- if (cycles.count <= ++cycles.hClock)
- break;
- case 263:
- case 271:
- case 279:
- case 287:
- case 295:
- case 303:
- case 311:
- case 319:
- {
- const byte* const buffer = oam.buffer + ((cycles.hClock - 263) / 2);
- if (buffer < oam.buffered)
- LoadSprite( io.pattern, FetchSpPattern(), buffer );
- if (cycles.count <= ++cycles.hClock)
- break;
- if (cycles.hClock == 320)
- goto HBlankBg;
- }
- case 264:
- case 272:
- case 280:
- case 288:
- case 296:
- case 304:
- case 312:
- OpenName();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- goto HBlankSp;
- case 320:
- HBlankBg:
- if (oam.buffer + (8*4) < oam.buffered)
- LoadExtendedSprites();
- OpenName();
- if (hActiveHook)
- hActiveHook.Execute();
- oam.latch = oam.ram[0];
- oam.buffered = oam.buffer;
- oam.spriteZeroInLine = false;
- oam.index = 0;
- oam.phase = &Ppu::EvaluateSpritesPhase0;
- cycles.hClock = 321;
- if (cycles.count <= 321)
- break;
- case 321:
- FetchName();
- cycles.hClock = 322;
- if (cycles.count <= 322)
- break;
- case 322:
- OpenAttribute();
- cycles.hClock = 323;
- if (cycles.count <= 323)
- break;
- case 323:
- FetchAttribute();
- scroll.ClockX();
- cycles.hClock = 324;
- if (cycles.count <= 324)
- break;
- case 324:
- OpenPattern( io.pattern | 0x0 );
- cycles.hClock = 325;
- if (cycles.count <= 325)
- break;
- case 325:
- FetchBgPattern0();
- cycles.hClock = 326;
- if (cycles.count <= 326)
- break;
- case 326:
- OpenPattern( io.pattern | 0x8 );
- cycles.hClock = 327;
- if (cycles.count <= 327)
- break;
- case 327:
- FetchBgPattern1();
- cycles.hClock = 328;
- if (cycles.count <= 328)
- break;
- case 328:
- PreLoadTiles();
- OpenName();
- cycles.hClock = 329;
- if (cycles.count <= 329)
- break;
- case 329:
- FetchName();
- cycles.hClock = 330;
- if (cycles.count <= 330)
- break;
- case 330:
- OpenAttribute();
- cycles.hClock = 331;
- if (cycles.count <= 331)
- break;
- case 331:
- FetchAttribute();
- scroll.ClockX();
- cycles.hClock = 332;
- if (cycles.count <= 332)
- break;
- case 332:
- OpenPattern( io.pattern | 0x0 );
- cycles.hClock = 333;
- if (cycles.count <= 333)
- break;
- case 333:
- FetchBgPattern0();
- cycles.hClock = 334;
- if (cycles.count <= 334)
- break;
- case 334:
- OpenPattern( io.pattern | 0x8 );
- cycles.hClock = 335;
- if (cycles.count <= 335)
- break;
- case 335:
- FetchBgPattern1();
- cycles.hClock = 336;
- if (cycles.count <= 336)
- break;
- case 336:
- OpenName();
- cycles.hClock = 337;
- if (cycles.count <= 337)
- break;
- case 337:
- tiles.mask = tiles.show[1];
- oam.mask = oam.show[1];
- if (scanline == SCANLINE_HDUMMY && model == PPU_RP2C02)
- {
- if (regs.frame)
- {
- output.burstPhase = (output.burstPhase + 2) % 3;
- cpu.SetFrameCycles( PPU_RP2C02_HVSYNC_1 );
- }
- else
- {
- output.burstPhase = (output.burstPhase + 1) % 3;
- }
- }
- cycles.hClock = 338;
- if (cycles.count <= 338)
- break;
- case 338:
- OpenName();
- if (scanline++ != 239)
- {
- const uint line = (scanline != 0 || model != PPU_RP2C02 || !regs.frame ? 341 : 340);
- cycles.hClock = 0;
- cycles.vClock += line;
- if (cycles.count <= line)
- break;
- cycles.count -= line;
- goto HActive;
- }
- else
- {
- if (ssleep >= 0)
- {
- scanline_sleep = 0;
- cycles.hClock = 0;
- cycles.vClock += 341;
- if (cycles.count <= 341)
- break;
- cycles.count -= 341;
- goto HActiveSleep;
- }
- else
- {
- cycles.hClock = HCLOCK_VBLANK_0;
- if (cycles.count <= HCLOCK_VBLANK_0)
- break;
- }
- }
- case HCLOCK_VBLANK_0:
- goto VBlank0;
- case HCLOCK_VBLANK_1:
- goto VBlank1;
- case HCLOCK_VBLANK_2:
- goto VBlank2;
- case HCLOCK_BOOT:
- goto Boot;
- case HCLOCK_DUMMY+0:
- regs.status = 0;
- scanline = SCANLINE_HDUMMY;
- case HCLOCK_DUMMY+8:
- case HCLOCK_DUMMY+16:
- case HCLOCK_DUMMY+24:
- case HCLOCK_DUMMY+32:
- case HCLOCK_DUMMY+40:
- case HCLOCK_DUMMY+48:
- case HCLOCK_DUMMY+56:
- case HCLOCK_DUMMY+64:
- case HCLOCK_DUMMY+72:
- case HCLOCK_DUMMY+80:
- case HCLOCK_DUMMY+88:
- case HCLOCK_DUMMY+96:
- case HCLOCK_DUMMY+104:
- case HCLOCK_DUMMY+112:
- case HCLOCK_DUMMY+120:
- case HCLOCK_DUMMY+128:
- case HCLOCK_DUMMY+136:
- case HCLOCK_DUMMY+144:
- case HCLOCK_DUMMY+152:
- case HCLOCK_DUMMY+160:
- case HCLOCK_DUMMY+168:
- case HCLOCK_DUMMY+176:
- case HCLOCK_DUMMY+184:
- case HCLOCK_DUMMY+192:
- case HCLOCK_DUMMY+200:
- case HCLOCK_DUMMY+208:
- case HCLOCK_DUMMY+216:
- case HCLOCK_DUMMY+224:
- case HCLOCK_DUMMY+232:
- case HCLOCK_DUMMY+240:
- case HCLOCK_DUMMY+248:
- HDummyBg:
- OpenName();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+2:
- case HCLOCK_DUMMY+10:
- case HCLOCK_DUMMY+18:
- case HCLOCK_DUMMY+26:
- case HCLOCK_DUMMY+34:
- case HCLOCK_DUMMY+42:
- case HCLOCK_DUMMY+50:
- case HCLOCK_DUMMY+58:
- case HCLOCK_DUMMY+66:
- case HCLOCK_DUMMY+74:
- case HCLOCK_DUMMY+82:
- case HCLOCK_DUMMY+90:
- case HCLOCK_DUMMY+98:
- case HCLOCK_DUMMY+106:
- case HCLOCK_DUMMY+114:
- case HCLOCK_DUMMY+122:
- case HCLOCK_DUMMY+130:
- case HCLOCK_DUMMY+138:
- case HCLOCK_DUMMY+146:
- case HCLOCK_DUMMY+154:
- case HCLOCK_DUMMY+162:
- case HCLOCK_DUMMY+170:
- case HCLOCK_DUMMY+178:
- case HCLOCK_DUMMY+186:
- case HCLOCK_DUMMY+194:
- case HCLOCK_DUMMY+202:
- case HCLOCK_DUMMY+210:
- case HCLOCK_DUMMY+218:
- case HCLOCK_DUMMY+226:
- case HCLOCK_DUMMY+234:
- case HCLOCK_DUMMY+242:
- case HCLOCK_DUMMY+250:
- OpenAttribute();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+4:
- case HCLOCK_DUMMY+12:
- case HCLOCK_DUMMY+20:
- case HCLOCK_DUMMY+28:
- case HCLOCK_DUMMY+36:
- case HCLOCK_DUMMY+44:
- case HCLOCK_DUMMY+52:
- case HCLOCK_DUMMY+60:
- case HCLOCK_DUMMY+68:
- case HCLOCK_DUMMY+76:
- case HCLOCK_DUMMY+84:
- case HCLOCK_DUMMY+92:
- case HCLOCK_DUMMY+100:
- case HCLOCK_DUMMY+108:
- case HCLOCK_DUMMY+116:
- case HCLOCK_DUMMY+124:
- case HCLOCK_DUMMY+132:
- case HCLOCK_DUMMY+140:
- case HCLOCK_DUMMY+148:
- case HCLOCK_DUMMY+156:
- case HCLOCK_DUMMY+164:
- case HCLOCK_DUMMY+172:
- case HCLOCK_DUMMY+180:
- case HCLOCK_DUMMY+188:
- case HCLOCK_DUMMY+196:
- case HCLOCK_DUMMY+204:
- case HCLOCK_DUMMY+212:
- case HCLOCK_DUMMY+220:
- case HCLOCK_DUMMY+228:
- case HCLOCK_DUMMY+236:
- case HCLOCK_DUMMY+244:
- case HCLOCK_DUMMY+252:
- OpenPattern( regs.ctrl[0] << 8 & 0x1000 );
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+6:
- case HCLOCK_DUMMY+14:
- case HCLOCK_DUMMY+22:
- case HCLOCK_DUMMY+30:
- case HCLOCK_DUMMY+38:
- case HCLOCK_DUMMY+46:
- case HCLOCK_DUMMY+54:
- case HCLOCK_DUMMY+62:
- case HCLOCK_DUMMY+70:
- case HCLOCK_DUMMY+78:
- case HCLOCK_DUMMY+86:
- case HCLOCK_DUMMY+94:
- case HCLOCK_DUMMY+102:
- case HCLOCK_DUMMY+110:
- case HCLOCK_DUMMY+118:
- case HCLOCK_DUMMY+126:
- case HCLOCK_DUMMY+134:
- case HCLOCK_DUMMY+142:
- case HCLOCK_DUMMY+150:
- case HCLOCK_DUMMY+158:
- case HCLOCK_DUMMY+166:
- case HCLOCK_DUMMY+174:
- case HCLOCK_DUMMY+182:
- case HCLOCK_DUMMY+190:
- case HCLOCK_DUMMY+198:
- case HCLOCK_DUMMY+206:
- case HCLOCK_DUMMY+214:
- case HCLOCK_DUMMY+222:
- case HCLOCK_DUMMY+230:
- case HCLOCK_DUMMY+238:
- case HCLOCK_DUMMY+246:
- case HCLOCK_DUMMY+254:
- OpenPattern( io.address | 0x8 );
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- if (cycles.hClock != HCLOCK_DUMMY+256)
- goto HDummyBg;
- case HCLOCK_DUMMY+256:
- case HCLOCK_DUMMY+264:
- case HCLOCK_DUMMY+272:
- case HCLOCK_DUMMY+280:
- case HCLOCK_DUMMY+288:
- case HCLOCK_DUMMY+296:
- case HCLOCK_DUMMY+312:
- HDummySp:
- OpenName();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+258:
- case HCLOCK_DUMMY+266:
- case HCLOCK_DUMMY+274:
- case HCLOCK_DUMMY+282:
- case HCLOCK_DUMMY+290:
- case HCLOCK_DUMMY+298:
- case HCLOCK_DUMMY+306:
- case HCLOCK_DUMMY+314:
- OpenName();
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+260:
- case HCLOCK_DUMMY+268:
- case HCLOCK_DUMMY+276:
- case HCLOCK_DUMMY+284:
- case HCLOCK_DUMMY+292:
- case HCLOCK_DUMMY+300:
- case HCLOCK_DUMMY+308:
- case HCLOCK_DUMMY+316:
- OpenPattern( OpenSprite() );
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- case HCLOCK_DUMMY+262:
- case HCLOCK_DUMMY+270:
- case HCLOCK_DUMMY+278:
- case HCLOCK_DUMMY+286:
- case HCLOCK_DUMMY+294:
- case HCLOCK_DUMMY+302:
- case HCLOCK_DUMMY+310:
- case HCLOCK_DUMMY+318:
- OpenPattern( io.address | 0x8 );
- if (cycles.hClock != HCLOCK_DUMMY+318)
- {
- cycles.hClock += 2;
- if (cycles.count <= cycles.hClock)
- break;
- if (cycles.hClock != HCLOCK_DUMMY+304)
- goto HDummySp;
- }
- else
- {
- cycles.hClock = 320;
- cycles.vClock += HCLOCK_DUMMY;
- cycles.count -= HCLOCK_DUMMY;
- if (cycles.count <= cycles.hClock)
- break;
- goto HBlankBg;
- }
- case HCLOCK_DUMMY+304:
- scroll.address = scroll.latch;
- goto HDummySp;
- default:
- NST_UNREACHABLE();
- }
- }
- else
- {
- switch (cycles.hClock)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- case 16:
- case 17:
- case 18:
- case 19:
- case 20:
- case 21:
- case 22:
- case 23:
- case 24:
- case 25:
- case 26:
- case 27:
- case 28:
- case 29:
- case 30:
- case 31:
- case 32:
- case 33:
- case 34:
- case 35:
- case 36:
- case 37:
- case 38:
- case 39:
- case 40:
- case 41:
- case 42:
- case 43:
- case 44:
- case 45:
- case 46:
- case 47:
- case 48:
- case 49:
- case 50:
- case 51:
- case 52:
- case 53:
- case 54:
- case 55:
- case 56:
- case 57:
- case 58:
- case 59:
- case 60:
- case 61:
- case 62:
- case 63:
- case 64:
- case 65:
- case 66:
- case 67:
- case 68:
- case 69:
- case 70:
- case 71:
- case 72:
- case 73:
- case 74:
- case 75:
- case 76:
- case 77:
- case 78:
- case 79:
- case 80:
- case 81:
- case 82:
- case 83:
- case 84:
- case 85:
- case 86:
- case 87:
- case 88:
- case 89:
- case 90:
- case 91:
- case 92:
- case 93:
- case 94:
- case 95:
- case 96:
- case 97:
- case 98:
- case 99:
- case 100:
- case 101:
- case 102:
- case 103:
- case 104:
- case 105:
- case 106:
- case 107:
- case 108:
- case 109:
- case 110:
- case 111:
- case 112:
- case 113:
- case 114:
- case 115:
- case 116:
- case 117:
- case 118:
- case 119:
- case 120:
- case 121:
- case 122:
- case 123:
- case 124:
- case 125:
- case 126:
- case 127:
- case 128:
- case 129:
- case 130:
- case 131:
- case 132:
- case 133:
- case 134:
- case 135:
- case 136:
- case 137:
- case 138:
- case 139:
- case 140:
- case 141:
- case 142:
- case 143:
- case 144:
- case 145:
- case 146:
- case 147:
- case 148:
- case 149:
- case 150:
- case 151:
- case 152:
- case 153:
- case 154:
- case 155:
- case 156:
- case 157:
- case 158:
- case 159:
- case 160:
- case 161:
- case 162:
- case 163:
- case 164:
- case 165:
- case 166:
- case 167:
- case 168:
- case 169:
- case 170:
- case 171:
- case 172:
- case 173:
- case 174:
- case 175:
- case 176:
- case 177:
- case 178:
- case 179:
- case 180:
- case 181:
- case 182:
- case 183:
- case 184:
- case 185:
- case 186:
- case 187:
- case 188:
- case 189:
- case 190:
- case 191:
- case 192:
- case 193:
- case 194:
- case 195:
- case 196:
- case 197:
- case 198:
- case 199:
- case 200:
- case 201:
- case 202:
- case 203:
- case 204:
- case 205:
- case 206:
- case 207:
- case 208:
- case 209:
- case 210:
- case 211:
- case 212:
- case 213:
- case 214:
- case 215:
- case 216:
- case 217:
- case 218:
- case 219:
- case 220:
- case 221:
- case 222:
- case 223:
- case 224:
- case 225:
- case 226:
- case 227:
- case 228:
- case 229:
- case 230:
- case 231:
- case 232:
- case 233:
- case 234:
- case 235:
- case 236:
- case 237:
- case 238:
- case 239:
- case 240:
- case 241:
- case 242:
- case 243:
- case 244:
- case 245:
- case 246:
- case 247:
- case 248:
- case 249:
- case 250:
- case 251:
- case 252:
- case 253:
- case 254:
- case 255:
- HActiveOff:
- {
- const uint pixel = output.palette[(scroll.address & 0x3F00) == 0x3F00 ? (scroll.address & 0x001F) : 0];
- uint i = cycles.hClock;
- const uint hClock = NST_MIN(cycles.count,256);
- NST_ASSERT( i < hClock );
- cycles.hClock = hClock;
- tiles.index = (hClock - 1) & 8;
- byte* const NST_RESTRICT tile = tiles.pixels;
- Video::Screen::Pixel* NST_RESTRICT target = output.target;
- do
- {
- tile[i++ & 15] = 0;
- *target++ = pixel;
- }
- while (i != hClock);
- output.target = target;
- if (cycles.count <= 256)
- break;
- }
- case 256:
- cycles.hClock = 257;
- if (cycles.count <= 257)
- break;
- case 257:
- if (hBlankHook)
- hBlankHook.Execute();
- oam.visible = oam.output;
- cycles.hClock = 258;
- if (cycles.count <= 258)
- break;
- case 258:
- case 260:
- case 261:
- case 262:
- case 263:
- case 264:
- case 266:
- case 268:
- case 269:
- case 270:
- case 271:
- case 272:
- case 274:
- case 276:
- case 277:
- case 278:
- case 279:
- case 280:
- case 282:
- case 284:
- case 285:
- case 286:
- case 287:
- case 288:
- case 290:
- case 292:
- case 293:
- case 294:
- case 295:
- case 296:
- case 298:
- case 300:
- case 301:
- case 302:
- case 303:
- case 304:
- case 306:
- case 308:
- case 309:
- case 310:
- case 311:
- case 312:
- case 314:
- case 316:
- case 317:
- case 318:
- case 319:
- if (cycles.count <= 320)
- {
- cycles.hClock = cycles.count + ((cycles.count & 0x7) == 3 || (cycles.count & 0x7) == 1);
- break;
- }
- case 320:
- HBlankOff:
- cycles.hClock = 321;
- if (hActiveHook)
- hActiveHook.Execute();
- oam.buffered = oam.buffer;
- oam.spriteZeroInLine = false;
- oam.index = 0;
- oam.phase = &Ppu::EvaluateSpritesPhase0;
- if (cycles.count <= 321)
- break;
- case 321:
- case 322:
- case 323:
- case 324:
- case 325:
- case 326:
- case 327:
- case 328:
- case 329:
- case 330:
- case 331:
- case 332:
- case 333:
- case 334:
- case 335:
- case 336:
- case 337:
- cycles.hClock = cycles.count;
- if (cycles.count <= 338)
- break;
- case 338:
- if (scanline++ != 239)
- {
- tiles.mask = tiles.show[1];
- oam.mask = oam.show[1];
- if (scanline == 0 && model == PPU_RP2C02)
- output.burstPhase = (output.burstPhase + 1) % 3;
- cycles.vClock += 341;
- cycles.hClock = 0;
- if (cycles.count <= 341)
- break;
- cycles.count -= 341;
- goto HActiveOff;
- }
- else
- {
- if (ssleep >= 0)
- {
- scanline_sleep = 0;
- cycles.vClock += 341;
- cycles.hClock = 0;
- if (cycles.count <= 341)
- break;
- cycles.count -= 341;
- goto HActiveSleep;
- }
- else
- {
- cycles.hClock = HCLOCK_VBLANK_0;
- if (cycles.count <= HCLOCK_VBLANK_0)
- break;
- }
- }
- case HCLOCK_VBLANK_0:
- goto VBlank0;
- case HCLOCK_VBLANK_1:
- goto VBlank1;
- case HCLOCK_VBLANK_2:
- goto VBlank2;
- case HCLOCK_BOOT:
- Boot:
- regs.status |= Regs::STATUS_VBLANK;
- cycles.hClock = HCLOCK_DUMMY;
- cycles.count = Cpu::CYCLE_MAX;
- if (cycles.reset)
- {
- switch (model)
- {
- case PPU_RP2C07: cycles.reset = PPU_RP2C07_HVREGBOOT - PPU_RP2C07_HVSYNCBOOT; break;
- case PPU_DENDY: cycles.reset = PPU_DENDY_HVREGBOOT - PPU_DENDY_HVSYNCBOOT; break;
- default: cycles.reset = PPU_RP2C02_HVREGBOOT - PPU_RP2C02_HVSYNCBOOT; break;
- }
- }
- return;
- case HCLOCK_DUMMY+0:
- regs.status = 0;
- scanline = SCANLINE_HDUMMY;
- case HCLOCK_DUMMY+2:
- case HCLOCK_DUMMY+4:
- case HCLOCK_DUMMY+6:
- case HCLOCK_DUMMY+8:
- case HCLOCK_DUMMY+10:
- case HCLOCK_DUMMY+12:
- case HCLOCK_DUMMY+14:
- case HCLOCK_DUMMY+16:
- case HCLOCK_DUMMY+18:
- case HCLOCK_DUMMY+20:
- case HCLOCK_DUMMY+22:
- case HCLOCK_DUMMY+24:
- case HCLOCK_DUMMY+26:
- case HCLOCK_DUMMY+28:
- case HCLOCK_DUMMY+30:
- case HCLOCK_DUMMY+32:
- case HCLOCK_DUMMY+34:
- case HCLOCK_DUMMY+36:
- case HCLOCK_DUMMY+38:
- case HCLOCK_DUMMY+40:
- case HCLOCK_DUMMY+42:
- case HCLOCK_DUMMY+44:
- case HCLOCK_DUMMY+46:
- case HCLOCK_DUMMY+48:
- case HCLOCK_DUMMY+50:
- case HCLOCK_DUMMY+52:
- case HCLOCK_DUMMY+54:
- case HCLOCK_DUMMY+56:
- case HCLOCK_DUMMY+58:
- case HCLOCK_DUMMY+60:
- case HCLOCK_DUMMY+62:
- case HCLOCK_DUMMY+64:
- case HCLOCK_DUMMY+66:
- case HCLOCK_DUMMY+68:
- case HCLOCK_DUMMY+70:
- case HCLOCK_DUMMY+72:
- case HCLOCK_DUMMY+74:
- case HCLOCK_DUMMY+76:
- case HCLOCK_DUMMY+78:
- case HCLOCK_DUMMY+80:
- case HCLOCK_DUMMY+82:
- case HCLOCK_DUMMY+84:
- case HCLOCK_DUMMY+86:
- case HCLOCK_DUMMY+88:
- case HCLOCK_DUMMY+90:
- case HCLOCK_DUMMY+92:
- case HCLOCK_DUMMY+94:
- case HCLOCK_DUMMY+96:
- case HCLOCK_DUMMY+98:
- case HCLOCK_DUMMY+100:
- case HCLOCK_DUMMY+102:
- case HCLOCK_DUMMY+104:
- case HCLOCK_DUMMY+106:
- case HCLOCK_DUMMY+108:
- case HCLOCK_DUMMY+110:
- case HCLOCK_DUMMY+112:
- case HCLOCK_DUMMY+114:
- case HCLOCK_DUMMY+116:
- case HCLOCK_DUMMY+118:
- case HCLOCK_DUMMY+120:
- case HCLOCK_DUMMY+122:
- case HCLOCK_DUMMY+124:
- case HCLOCK_DUMMY+126:
- case HCLOCK_DUMMY+128:
- case HCLOCK_DUMMY+130:
- case HCLOCK_DUMMY+132:
- case HCLOCK_DUMMY+134:
- case HCLOCK_DUMMY+136:
- case HCLOCK_DUMMY+138:
- case HCLOCK_DUMMY+140:
- case HCLOCK_DUMMY+142:
- case HCLOCK_DUMMY+144:
- case HCLOCK_DUMMY+146:
- case HCLOCK_DUMMY+148:
- case HCLOCK_DUMMY+150:
- case HCLOCK_DUMMY+152:
- case HCLOCK_DUMMY+154:
- case HCLOCK_DUMMY+156:
- case HCLOCK_DUMMY+158:
- case HCLOCK_DUMMY+160:
- case HCLOCK_DUMMY+162:
- case HCLOCK_DUMMY+164:
- case HCLOCK_DUMMY+166:
- case HCLOCK_DUMMY+168:
- case HCLOCK_DUMMY+170:
- case HCLOCK_DUMMY+172:
- case HCLOCK_DUMMY+174:
- case HCLOCK_DUMMY+176:
- case HCLOCK_DUMMY+178:
- case HCLOCK_DUMMY+180:
- case HCLOCK_DUMMY+182:
- case HCLOCK_DUMMY+184:
- case HCLOCK_DUMMY+186:
- case HCLOCK_DUMMY+188:
- case HCLOCK_DUMMY+190:
- case HCLOCK_DUMMY+192:
- case HCLOCK_DUMMY+194:
- case HCLOCK_DUMMY+196:
- case HCLOCK_DUMMY+198:
- case HCLOCK_DUMMY+200:
- case HCLOCK_DUMMY+202:
- case HCLOCK_DUMMY+204:
- case HCLOCK_DUMMY+206:
- case HCLOCK_DUMMY+208:
- case HCLOCK_DUMMY+210:
- case HCLOCK_DUMMY+212:
- case HCLOCK_DUMMY+214:
- case HCLOCK_DUMMY+216:
- case HCLOCK_DUMMY+218:
- case HCLOCK_DUMMY+220:
- case HCLOCK_DUMMY+222:
- case HCLOCK_DUMMY+224:
- case HCLOCK_DUMMY+226:
- case HCLOCK_DUMMY+228:
- case HCLOCK_DUMMY+230:
- case HCLOCK_DUMMY+232:
- case HCLOCK_DUMMY+234:
- case HCLOCK_DUMMY+236:
- case HCLOCK_DUMMY+238:
- case HCLOCK_DUMMY+240:
- case HCLOCK_DUMMY+242:
- case HCLOCK_DUMMY+244:
- case HCLOCK_DUMMY+246:
- case HCLOCK_DUMMY+248:
- case HCLOCK_DUMMY+250:
- case HCLOCK_DUMMY+252:
- case HCLOCK_DUMMY+254:
- case HCLOCK_DUMMY+256:
- case HCLOCK_DUMMY+258:
- case HCLOCK_DUMMY+260:
- case HCLOCK_DUMMY+262:
- case HCLOCK_DUMMY+264:
- case HCLOCK_DUMMY+266:
- case HCLOCK_DUMMY+268:
- case HCLOCK_DUMMY+270:
- case HCLOCK_DUMMY+272:
- case HCLOCK_DUMMY+274:
- case HCLOCK_DUMMY+276:
- case HCLOCK_DUMMY+278:
- case HCLOCK_DUMMY+280:
- case HCLOCK_DUMMY+282:
- case HCLOCK_DUMMY+284:
- case HCLOCK_DUMMY+286:
- case HCLOCK_DUMMY+288:
- case HCLOCK_DUMMY+290:
- case HCLOCK_DUMMY+292:
- case HCLOCK_DUMMY+294:
- case HCLOCK_DUMMY+296:
- case HCLOCK_DUMMY+298:
- case HCLOCK_DUMMY+300:
- case HCLOCK_DUMMY+302:
- case HCLOCK_DUMMY+304:
- case HCLOCK_DUMMY+306:
- case HCLOCK_DUMMY+308:
- case HCLOCK_DUMMY+310:
- case HCLOCK_DUMMY+312:
- case HCLOCK_DUMMY+314:
- case HCLOCK_DUMMY+316:
- {
- NST_COMPILE_ASSERT( HCLOCK_DUMMY & 1 );
- cycles.hClock = cycles.count | 1;
- if (cycles.count <= HCLOCK_DUMMY+318)
- break;
- }
- case HCLOCK_DUMMY+318:
- cycles.hClock = 320;
- cycles.vClock += HCLOCK_DUMMY;
- cycles.count -= HCLOCK_DUMMY;
- if (cycles.count <= 320)
- break;
- goto HBlankOff;
- default:
- NST_UNREACHABLE();
- }
- }
- cycles.count = GetCycles();
- }
- }
- }
|