Stuck with PPU emulation (Donkey Kong)

Discuss emulation of the Nintendo Entertainment System and Famicom.

Moderator: Moderators

User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Hi all,

I am going to make one of those posts with a screenshot, not much information, and a general question of what am I doing wrong. Feel free to ignore and move on to next post. I know how frustrating these types of posts are.

I have been implementing a NES emulator in Swift for the iPhone/iPad (just for fun) and am really stuck on the PPU emulation. I have read heaps of documentation on the PPU and looked at other peoples code (Fogleman's GO version is so clean) and believe I have a pretty good understanding of how most parts work: pattern tables, nameable, attribute table, palette, memory mapping, etc. I haven't implemented name table horizontal/vertical mapping, attribute table, or palettes (have hard coded one), nor am I doing any scrolling. Although I have implemented a lot of code for it, I'm not doing any shifting of the latches. I have loaded up Donkey Kong and finally have some graphics on the screen, unfortunately it doesn't look anything like the Donkey Kong Title screen.

Mine:
Screenshot 2018-08-30 13.55.17.png
The orange are the horizontal and vertical blank pixels.

What it should look like:
dk1.png
dk1.png (22.21 KiB) Viewed 20066 times

Here is the bit where I ask what I have done wrong. I guess I am just hoping someone has seen something similar to this when they were first implementing their emulator and can point me in the right direction. I am happy to upload my PPU code if needed but was not sure anyone wants to do a 800 line code review. Any help, pointers, guesses etc welcome.

Cheers,
Brett
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Stuck with PPU emulation (Donkey Kong)

Post by zeroone »

Did you vet your CPU with the test roms?
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Stuck with PPU emulation (Donkey Kong)

Post by koitsu »

This looks like a multitude of problems; some emulation-oriented, some graphical, and probably some CPU bugs.

Two things that stand out above all else to me:

1. Nametable contents are not what they should be. If the nametable data was correct but CHR was wrong, you'd have the "visual layout" of the tiles correct (spelling out "Donkey Kong" etc.) but with improper tiles. That isn't the case here -- in this case, the nametable data is wrong, as is the CHR data,

2. The CHR data is completely skewed in bizarre ways. There are multiple severe problems. These are the ones I see:

- Some tiles are "offset" by what looks like a row or column of pixels. The "7" in the further upper-left corner is an example, but same goes for the furthest right column of tiles, ditto with the first line/row of tiles at the top,
- Some tiles are corrupted badly, such as the first "9" in the upper left, the following "S", the following "0", the following "3", and several "F"s. Regarding the "F"s, notice how they're not even the same universally across all the tiles -- some "F"s look "thinner" in weight, while others look "fatter" (the latter is correct) -- there is only one "F" font/letter in Donkey Kong's CHR data and it's nice and fat,
- Palette is wrong (worry about that later).

These problems look incredibly deep. The biggest concern is that there's something very anomalous about your drawing (or possibly "graphics decoding/translation") routine. This isn't a case of "the wrong CHR data", this is a case of what appears to be variance in tile corruption (of the actual tile data). All the tiles should be universally identical (unless the CHR data in the ROM says otherwise (it doesn't, see below)).

Very bad CPU bugs could allow for the running PRG code to execute faulty operations causing writes to PPU RAM (pattern table areas), and potentially corrupting the graphics via 6502 code. However:

Donkey Kong is a mapper 0 game with 16KB PRG and 8KB CHR-ROM (i.e. pattern table data is read-only, so any writes to PPU pattern table should basically do nothing -- and Donkey Kong's code doesn't do this anyway), so there is no chance you've got "the wrong PRG/CHR page". Mapper 0 games make great test subjects; Mario Brothers (not Super!) is another good one (and actually the first one I ever got working in emulators I've worked on).

This is a case of something very deep/wrong with your emulator. I don't think anyone will willingly volunteer sifting through thousands of lines to figure out what's wrong; the person who knows the code best... is you! :-)

I know you're a Mac user, but I recommend you use WINE or some PC emulator and get familiar with FCEUX. It has a lot of very good debugging capabilities that can help you figure out what may be wrong with your own emulator. I've attached a screenshot of what the PPU RAM should look like, visually, during the title screen. I should be clear about when this shot was taken: it was taken right after power-on, *before* the game had a chance to switch from title screen to attract mode and back to title. (The palette contents are quite different after going from attract back to title, because several palette entries are updated during attract that title didn't set :-) )

If you aren't sure how to interpret some of the Wiki data or PPU details, feel free to ask. It might be worth re-evaluating how you do tile lookups/etc. just to be sure you have the formula right, and ask folks "is this correct?" Be sure to explain what all of your variables are/do for that kind of addressing formula. I find the Wiki's description of some PPU-related bits (esp. the basics) difficult to follow, so you might consider reading something like my old nestech.txt document to get a better understanding of nametable vs. pattern vs. attribute.

Hope this helps. Good luck, and keep us posted on your progress!
Attachments
Capture.PNG
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Thanks heaps for replying to my really vague post, I normally don't make those kinds of posts on any forum but I wasn't really sure where to start on this one.

@zeroone I spent quite a few months on the CPU and ran the nestest.rom and compared my log against the published one. I didn't start the PPU until I had the CPU logs matching exactly. I haven't run those tests you linked to though, I will give them a go, thanks for the link.

@koitsu Thank you so much for taking time to give some great explanations on what could be wrong, and it looks like a lot :-D

You are right, it is not just a corruption in the name tables, I hadn't noticed the different F characters, I just thought I might be a pixel out somewhere, but it is worse than that. My emulator doesn't allow writes from the CPU to PPU RAM unless it is through the $200x registers. So I am not sure how the pattern tables are getting corrupted, but I will look into it. I am hoping to fix the name tables first so the screen looks somewhat correct, I think it will make it easier to fix issues with pixel offset and row column offsets.

I used my sons PC to run FCEUX last night and have managed to have a look at the nameable and pattern table but have yet to work out how to put a breakpoint in the right place to get the contents at the right time as you have done. I need to spend more time on it this weekend. Has been fun teaching my 10 year old what I am doing and have even had him operating FCEUX while I debug my code. I think we will be FCEUX experts by the time I finish my emulator.

I am pretty sure my understanding of name tables, pattern tables etc is correct, have read many different documents, blogs, and of course the Wiki until I got it in my head what each part does. I think (hope) it is just my implementation of these that I have incorrect. I spend hours coding for the day job and get home quite late, I then code after family has gone to bed so concentration levels are not what they should be. I am thinking it may be my MemoryMapper that is the main culprit as I struggled with this more than any other component, not to say the PPU doesn't have its obvious bugs :-)

You have given me a lot to think about. I will first run the CPU tests that @zeroone linked to as I haven't run those ones. And then spend a lot of time in FCEUX comparing that to what I have.

Thanks again for the replies, love this forum.

Cheers,
Brett
User avatar
zeroone
Posts: 939
Joined: Mon Dec 29, 2014 1:46 pm
Location: New York, NY
Contact:

Re: Stuck with PPU emulation (Donkey Kong)

Post by zeroone »

iOSBrett wrote:I used my sons PC to run FCEUX last night and have managed to have a look at the nameable and pattern table but have yet to work out how to put a breakpoint in the right place to get the contents at the right time as you have done. I need to spend more time on it this weekend. Has been fun teaching my 10 year old what I am doing and have even had him operating FCEUX while I debug my code. I think we will be FCEUX experts by the time I finish my emulator.
By the way, Nintaco works on the Mac. It provides similar debugging features.
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Just a quick update:

1. Nintaco works really great, much easier to debug on same machine as my emulator, thanks for letting me know @zeroone

2. I found a BIG problem in my emulator. I was driving home from work the other night (is a 90 min trip) and I was thinking about all the thinks that @koitsu had said and even what I said in my reply, when it hit me. My nameable was not writable. I was (and maybe still am) confusing CHR Data with Nameable memory. I was thinking they were pretty much the same thing and reads from 0x2000 in CHR Data from the ROM file was my nameable, and I was also not allowing writing back to the ROM. So nothing could write to the nameable and my reads were from the wrong place. I updated this and unfortunately it is not much better, but it is different. My initial nameable and screen is full of 0's. And for some reason it takes around 30 seconds before a write to the nameable. I can see that at this 30 second point tile 0x24 is being written to PPU Register 0x2007 many times, I think this is a good thing as that is a fully black tile, other tiles are also written. However these tiles are written to my screen a little bit all over the shop. But it is a good start.

3. I found a bug in my incrementY() method which was pretty much a copy from the Wiki, just had a bracket in the wrong place.

I do have one question though. When running Nintaco I saw that the Donkey Kong intro screen was displayed immediately after a reset. Am I correct in assuming that this is written through Register 0x2007 as I see in my emulator after 30 seconds, or is there some way that the nameable is initialised from the CHR Data in one go ?

Cheers,
Brett
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Stuck with PPU emulation (Donkey Kong)

Post by koitsu »

A screen full of zeros -- meaning the tile that represents the number "0" -- is good progress in a way. I'll save why until the end, to make you read what I've written. ;-)

Understanding PPU RAM layout (meaning what addresses in PPU RAM are for what) is pretty easy: https://wiki.nesdev.com/w/index.php/PPU_memory_map

CHR-ROM -- meaning the literal 8KBytes of CHR data you have in the ROM file -- are *literally* the Pattern Table. Now you know why the CHR data in NES files happens to be 8KBytes. CHR data is "tile data", i.e. the stuff depicted in the FCEUX screenshot I provided. This, per tile, represents the lower 2 bits that make up the palette index to refer to. There's 16 bytes per tile. The "ROM" part of "CHR-ROM" means the pattern table is read-only (i.e. if 6502 attempted lda #$00 / sta $2006 / lda #$00 / sta $2006 / lda #$7f / sta $2007 to write $7F to PPU RAM $0000, it would do nothing), because in hardware it's literally mapped to a mask ROM chip. See here for what's physically on a Donkey Kong cart -- one chip for PRG-ROM, one chip for CHR-ROM. If the cart had CHR-RAM, the pattern table areas would be writeable (and 6502 code would be used to populate them with graphics).

Nametable is mostly for screen layout, i.e. what tile (CHR) should be shown where on the screen, with one exception:

Each nametable also includes its own attribute table (64 bytes worth), e.g. $23C0-23FF for nametable 0, which is what defines the upper 2 bits that make up the palette index to refer to. These bits are used for each 2x2 tile (or 16x16 pixel) "quadrant" on the screen.

On a per-tile basis, you "combine" the bits from the pattern table with the bits from the nametable to make 4 bits (a nybble), and that represents which actual index in the palette to refer to when drawing a colour on screen.

You should probably re-read or review these pages again:

https://wiki.nesdev.com/w/index.php/PPU_pattern_tables
https://wiki.nesdev.com/w/index.php/PPU_nametables
https://wiki.nesdev.com/w/index.php/PPU ... ute_tables

Strong matter of opinion, but I've maintained for a while that the Wiki does a *horrible, awful* job of teaching someone how NES graphics are "put together". I still maintain my nestech.txt document does a better job. I've said that for 20 years as someone who really didn't understand how the attribute table "fit in" to the whole scheme of things, until one day, my roommate explained it to me in such a way that something went off in my head and suddenly bam, it all made sense.

You can actually get by not worrying about the attribute table when starting/developing an emulator (i.e. relying entirely on the pattern table, and leaving the upper 2 bits of the calculated palette index as zero) -- yes, the colours will be wrong, but you will definitely know if things are correct layout-wise (nametable-wise) for the most part. That's usually what I recommend to new emulator authors: if the attribute table confuses you, don't implement it into your formulas yet, just work off nametable + pattern table until you get something looking mostly right.

Thirty seconds to write something to the nametable sounds to me like you either have some code of your own that's spinning/wasting time (a common mistake is to be copying tons of data around -- use pointers, don't copy), or you have something very strangely implemented in your 6502 core that's causing very long or infinite loops or other delays. You might want to start implementing some 6502 debugging to a text file so that you can see exactly what instructions are being executed and when.

Back to "a screen filled with zeros":

Look closely at the screenshot I provided from FCEUX: the tile that represents the number "0" happens to be tile $00 in the upper pattern table, so pattern table 1 (i.e. $1000-1FFF in PPU RAM). Thus, a nametable filled with zeros would visually show a "0" tile on the screen. But we both know that isn't what Donkey Kong shows for its title screen, so what gives?

The answer has to do with nametable mirroring. You probably have seen the terms "vertical" and "horizontal" used throughout the Wiki -- if not, that page I just linked will explain it to you. There is a mirroring bit in the NES file header that defines vertical vs. horizontal. A *lot* of people implement these backwards the first time -- what the think horizontal means is actually vertical, and vice-versa. You'll understand when you read the Wiki.

If your emulator is using the wrong mirroring model, you could end up displaying the wrong data.

Another possibility is that you've not implemented nametable selection correctly, re: bits 1-0 of $2000. This is easy to state in a one-liner but it's actually much more complicated given how the PPU renders data and how it uses $2000 + $2005 + $2006 to calculate what to read from (to draw) -- and when. That subject is not for the faint of heart.

Another possibility is that you have a Donkey Kong ROM with the mirroring bit set wrong in the NES header. The game uses horizontal mirroring per the NES file header. I recommend using Donkey Kong (W) (PRG1) [!].nes, MD5 checksum of 40319cad12c80fc095901eb0182df838. In the future, when discussing problems with games / asking for help with a game, you should always disclose the ROM filename and the MD5 checksum -- it is incredibly common for Person X to be talking about a problem that Person Y cannot reproduce, all because Person X has a different (or buggy) ROM.

Another hint: in Donkey Kong's title screen, PPU RAM $2800-BFFF and $2C00-2FFF contains all zeros. Donkey Kong's title screen uses PPU RAM $2000-23FF and/or $2400-27FF (since it uses horizontal mirroring). See FCEUX's Nametable Viewer for details -- note you can mouse over parts of the window and see what tile and PPU RAM address are referenced. It's best to pause the emulator when doing this.

All that said: a value of $24 for a nametable byte is also good -- that is indeed a blank/empty tile from pattern table 1. For the tile screen, the first non-blank tile (non-$24 tile) that's drawn is tile $62 (top left corner of the "D" in "DONKEY KONG"). Those, and tile $24 (blank space), are repeated for a while to make up the "DONKEY KONG" logo/text. The next non-blank tile you'll find is tile $01 (the number "1" in "1 PLAYER GAME A"). I'm going completely off of what the nametable has in it once its rendered, not necessarily the order of writes to PPU RAM per 6502 code execution (I'd have to look at a trace log for that).
User avatar
davecom
Posts: 39
Joined: Mon Jul 16, 2018 2:57 pm

Re: Stuck with PPU emulation (Donkey Kong)

Post by davecom »

Hey iOSBrett,

I see you used the screenshot from my not-yet-working emulator in your comparison. I can't give you a better reply than you've already received in this thread, because I don't know enough to... I'm just writing to offer some encouragement. I had similar garbage spewing in my emulator before I got the backgrounds of Donkey Kong working (including the 0s you describe) and I was only a few small source changes away from getting backgrounds rendering. With the help of the fine folks in this forum, I got there. My issues were a combination of unrealized CPU issues, timing issues, and simple programming logic issues. Basically, I'm writing to say that I think you're probably closer than you think to getting something that resembles Donkey Kong rendering. My only advice is to debug print a lot and check your assumptions.

Best wishes!
iOSBrett wrote:Hi all,

I am going to make one of those posts with a screenshot, not much information, and a general question of what am I doing wrong. Feel free to ignore and move on to next post. I know how frustrating these types of posts are.

I have been implementing a NES emulator in Swift for the iPhone/iPad (just for fun) and am really stuck on the PPU emulation. I have read heaps of documentation on the PPU and looked at other peoples code (Fogleman's GO version is so clean) and believe I have a pretty good understanding of how most parts work: pattern tables, nameable, attribute table, palette, memory mapping, etc. I haven't implemented name table horizontal/vertical mapping, attribute table, or palettes (have hard coded one), nor am I doing any scrolling. Although I have implemented a lot of code for it, I'm not doing any shifting of the latches. I have loaded up Donkey Kong and finally have some graphics on the screen, unfortunately it doesn't look anything like the Donkey Kong Title screen.

Mine:
Screenshot 2018-08-30 13.55.17.png
The orange are the horizontal and vertical blank pixels.

What it should look like:
dk1.png

Here is the bit where I ask what I have done wrong. I guess I am just hoping someone has seen something similar to this when they were first implementing their emulator and can point me in the right direction. I am happy to upload my PPU code if needed but was not sure anyone wants to do a 800 line code review. Any help, pointers, guesses etc welcome.

Cheers,
Brett
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Update time.

First thank you to @koitsu for the above post, all of the information helped me A LOT!!! Some of it I already knew, but even then you need someone to explain it in a different way to get it through to you. I followed a lot of your advice and found quite a few bugs, some quite big ones.

Also thanks to @zeroone, without Nintaco I would not have found my last 2 bugs (more below).

Finally thanks to @davecom who's post I didn't actually see until today. I was coming here to post up that I had given up on my Emulator when I saw his post. This gave me the boost of energy I needed to solve the last 2 bugs, thanks for the pep talk, it really helped.

The significant bugs I found where:
- I had implemented a debugger when I was writing my CPU, before even starting the PPU. It was pretty fancy and I was pretty proud of it, hence it was my downfall. My debugger read ahead in order to display what the next command would be if you did a step. It displayed not only the contents from the code, but also from the memory, even to the level of the PPU registers. But what happens when you read a PPU register, particularly $2002 & $2007 ? You cause side effects! So for every real read, I was actually doing 2. This means the latch toggle, was always toggled back straight away, and the last read value was wrong, and more importantly "v" was incorrect.

- I wrote some fancy bit sitting methods in Swift that could individually, set, clear, and toggle bits. Except the set did not work correctly. This code was used in quite a few places, but caused havoc when reading $2002, I was using it to set bits 5, 6, and 7(nmi).

- I missed a line in reading $2002, a pretty simple one "v = t"
- In my incrementY() that I copied from the Wiki I had a misplaced bracket, which was setting coarse Y into v only if y didn't equal 31.

The last two which I found after reading @davecom's post was by basically comparing 28,000 lines of nintanco's log with my own:
- I was not checking the PPUMask.showBackground flag in my PPU tick method, this meant I was always changing the value of v, and nothing was ever going to go right doing that. This resulted in a black background with a few random tiles, instead of a whole bunch of "00".
- For some reason I either changed my implementation of CPU absoluteX and absoluteY addressing mode, or they were never correct. Which is weird because I ran all 9000 lines of the CPU test rom and it passed. I found this around line 26,000 in my comparisons.

Having fixed all of the above, it still has many issues, but they all look fixable, some are because I haven't implemented those features yet (attribute tables, palettes, shift registers, nametable mirroring) etc.
My DK1.png
My DK2.png
Thanks again for everyones help,
Brett
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Quick update.

I love it when a one line change makes a big difference
Screenshot 2018-10-17 12.09.54.png

Code: Select all

    lazy var palette : [[UInt8]] = [ [ 0, 0, 0],
                                     [ 255, 0, 0],
                                     [ 0, 255, 0],
                                     [ 0, 0, 255]]

    func drawPixel()
    {
        if cycle > 240 { return }

        let x = cycle
        let y = scanline

        let highTile = UInt8(shiftRegisterTileA)
        let lowTile = UInt8(shiftRegisterTileB)

        let bit = (7 - cycle%8)
        let index = (highTile.get( bit:bit) << 1) + lowTile.get( bit:bit)

        let color = palette[index]

        pixelBuffer.setPixel( x:x, y:y, r:color[0], g:color[1], b:color[2])
    }
Just changed to subtracting 1 from the cycle before selecting the bit. I stole that fix from fogleman's GO emulator. His code is so clean and easy to read.

Code: Select all

       let bit = (7 - (cycle-1)%8)
However I still have some corruption. Screen goes all weird between title screen and next screen and then settles on this. Looks like random data is getting written to the scroll registers, but when it does get written the value is always 0. Another problem for another day. Am pretty stoked with how far I have gotten since starting this in April.
Also changed to the ROM suggested by @koitsu
Screenshot 2018-10-17 12.11.42.png
Still have the 30 second delay before title screen shows up. Logs look the same as Nintanco which makes me worried my emulator is just slow, but pretty sure it is doing 60fps.
User avatar
davecom
Posts: 39
Joined: Mon Jul 16, 2018 2:57 pm

Re: Stuck with PPU emulation (Donkey Kong)

Post by davecom »

Congrats! That's awesome progress. Now, I feel bad because here I was pep-talking you, while I actually have not had the energy to continue my own emulator. I next need to conquer sprites; but I feel like it's the kind of thing you need a couple days of solid time to do, and I don't think I will have that for a_while. But I'm so glad to hear writing out here in the ether of the internet actually had a positive effect on someone; when I got to your stage on the backgrounds, every little fix led to big improvements. I'm curious about your perceived performance issues; hope it's not a Swift thing! Congrats again and best wishes.

PS Fogleman's emulator is awesome, agreed; I wouldn't have completed my backgrounds without reading his; the PPU of my emulator so far is basically a mish-mash of the Wiki and a bad port of his.
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

I never get much solid time to work on it as I am away from home for 13 hours a day and I have kids. So sometimes I don't touch it for a few weeks and other times I will get 6 hours on a Sunday. So it can be hard to find the time some days, and hard to find the motivation on others. But you definitely were responsible for me not chucking it all in last weekend. My point is that you shouldn't aim to get the Sprites done in one Big Bang, or you will never start it. Aim for small things, getting sprite data into the PPU, drawing something/anything on the screen even if it is crap, then one bug fix at a time.

For some reason I am not too worried about Sprites, it has to be easier than this background stuff right? right? :-D
The thing that scares me is the APU, I have done some sound programming on iOS and used to play around with it on the C64 when I was a kid. But I'm not looking forward to that.

I do Swift for my day job and haven't found any performance issues there, apart from taking way too long to compile. I think it is a bug in my code somewhere, it's currently hiding behind all of the other bugs.

The structure of my PPU was definitely inspired by fogleman, I try not to look at his code too much though, only when I get super stuck. All the code for incrementXY() and copyHorizontalVertical() comes directly from the Wiki. I have learnt so much from both his code and the Wiki. I follow him on youtube and twitter, the guy is very smart and seems to churn out projects with ease, I hate him ;-p
User avatar
koitsu
Posts: 4201
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Stuck with PPU emulation (Donkey Kong)

Post by koitsu »

Excellent progress!
User avatar
iOSBrett
Posts: 38
Joined: Wed Apr 18, 2018 1:09 am
Location: Australia

Re: Stuck with PPU emulation (Donkey Kong)

Post by iOSBrett »

Thanks @koitsu

Also I read your nestech.txt document, man I wish I had of found that 6 months ago! So easy to read and understand.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Stuck with PPU emulation (Donkey Kong)

Post by tepples »

iOSBrett wrote:Thanks @koitsu

Also I read your nestech.txt document, man I wish I had of found that 6 months ago! So easy to read and understand.
That's what happens when someone with actual technical writing expertise writes technical docs. Because that isn't common among editors of the wiki, a lot of the wiki isn't quite as easy to read as what koitsu has written. Fortunately, the wiki now contains an updated nestech.txt that incorporates more recent hardware findings and best practices.
Post Reply