NstPpu.cpp 72 KB

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