8x16 and whatever else unreg wants to know

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Mon May 20, 2019 2:42 pm

After turning rendering off, the screen is wiped. Why? Did they design the PPU to do that? :? Maybe it makes sense though, bc, I guess, the screen requires the PPU to draw it every frame; and turning off the PPU's drawing restricts future screens from showing. If that's so, it would have been ultra cool to have installed a feature that made the PPU just draw the last screen written until rendering is reenabled. Maybe that would be to complex.

Too bad that $2001 can only be written to during vblank. It seems to me: if that wasn't the case the screen wouldn't clear bc rendering would be reenabled before the end of the frame.

Is the only way to avoid blank-screens appearing inbetween screens drawn by the PPU, is to draw each screen inside vblank so that rendering isn't disabled? I'm asking this here bc the nesdev wiki claims that screens can't be drawn outside of vblank. :roll: :)

Note to myself: have I asked this before?

lidnariq
Posts: 8692
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 8x16 and whatever else unreg wants to know

Post by lidnariq » Mon May 20, 2019 2:55 pm

unregistered wrote:After turning rendering off, the screen is wiped. Why? Did they design the PPU to do that? :? Maybe it makes sense though, bc, I guess, the screen requires the PPU to draw it every frame; and turning off the PPU's drawing restricts future screens from showing.
The picture literally only exists at the exact moment that each pixel is sent to the CRT. The rest is just the optical illusion known as persistence of vision.
Too bad that $2001 can only be written to during vblank. It seems to me: if that wasn't the case the screen wouldn't clear bc rendering would be reenabled before the end of the frame.
$2001 can be written at any time. But for the image to appear, you have to wait for the CRT to draw it. Turning on rendering using $2001 doesn't cause the entire set of pixels to be sent all at once; instead it starts sending pixels gradually, one new pixel every .000000182 seconds.
I'm asking this here bc the nesdev wiki claims that screens can't be drawn outside of vblank.
You cannot write new data during rendering, no.

supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: 8x16 and whatever else unreg wants to know

Post by supercat » Mon May 20, 2019 3:40 pm

lidnariq wrote:
unregistered wrote:After turning rendering off, the screen is wiped. Why? Did they design the PPU to do that? :? Maybe it makes sense though, bc, I guess, the screen requires the PPU to draw it every frame; and turning off the PPU's drawing restricts future screens from showing.
The picture literally only exists at the exact moment that each pixel is sent to the CRT. The rest is just the optical illusion known as persistence of vision.
Too bad that $2001 can only be written to during vblank. It seems to me: if that wasn't the case the screen wouldn't clear bc rendering would be reenabled before the end of the frame.
$2001 can be written at any time. But for the image to appear, you have to wait for the CRT to draw it. Turning on rendering using $2001 doesn't cause the entire set of pixels to be sent all at once; instead it starts sending pixels gradually, one new pixel every .000000182 seconds.
I'm asking this here bc the nesdev wiki claims that screens can't be drawn outside of vblank.
You cannot write new data during rendering, no.
There are two issues at play here:

1. The NES is designed to drive a device that draws a picture by modulating a moving electron beam; the NES sends out a signal that controls how bright the spot under the beam should be at any given moment. Turning off rendering will cause the beam to just keep outputting a solid color until rendering is turned back on, but that will only affect the parts of the picture drawn by the beam while rendering was off. If rendering is left off, then it will affect the whole picture as the beam passes over it. Rendering is only enabled when the render control bits are set and the beam's scanning process isn't between the bottom of one frame and the start of the next--a time known as the "vertical blanking interval", or "vblank".

2. On machines designed for connect to NTSC-based televisions, the memory cells used to hold sprite positions and attributes (Object Attribute Memory, or OAM) may arbitrarily flip state if rendering is disabled for much longer than vblank. So leaving rendering disabled for too long may effectively "wipe" the OAM.

The first issue is common to many vintage systems. The latter is so far as I can tell unique to the NES.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Mon May 20, 2019 6:29 pm

lidnariq wrote:
Too bad that $2001 can only be written to during vblank. It seems to me: if that wasn't the case the screen wouldn't clear bc rendering would be reenabled before the end of the frame.
$2001 can be written at any time. But for the image to appear, you have to wait for the CRT to draw it. Turning on rendering using $2001 doesn't cause the entire set of pixels to be sent all at once; instead it starts sending pixels gradually, one new pixel every .000000182 seconds.
supercat wrote:There are two issues at play here:

1. The NES is designed to drive a device that draws a picture by modulating a moving electron beam; the NES sends out a signal that controls how bright the spot under the beam should be at any given moment. Turning off rendering will cause the beam to just keep outputting a solid color until rendering is turned back on, but that will only affect the parts of the picture drawn by the beam while rendering was off. If rendering is left off, then it will affect the whole picture as the beam passes over it. Rendering is only enabled when the render control bits are set and the beam's scanning process isn't between the bottom of one frame and the start of the next--a time known as the "vertical blanking interval", or "vblank".

2. On machines designed for connect to NTSC-based televisions, the memory cells used to hold sprite positions and attributes (Object Attribute Memory, or OAM) may arbitrarily flip state if rendering is disabled for much longer than vblank. So leaving rendering disabled for too long may effectively "wipe" the OAM.

The first issue is common to many vintage systems. The latter is so far as I can tell unique to the NES.
So, since there seem to be 61,440 pixels in an entire (not just the visible part of NTSC) NES screen (32x8+30x8==61440) and drawing a screen it must take 61440 x .000000182 == 0.01118208 seconds after rendering is reenabled for the CRT to fully draw it, it must be possible to disable rendering, write a screen to the PPU, and reenable rendering a little over one hundreth of a second before vblank so that the screen appears before the OAM is wiped right? :) But, supercat says that the OAM can be wiped if rendering is off for a little longer than vblank, but let's say it doesn't matter that the OAM is wiped. That just affects coloring for us, I guess... it would be really cool to see it work without blinking. :) Going to try the current code on the powerpak tomorrow to see if the blinking is just Mesen.
lidnariq wrote:
I'm asking this here bc the nesdev wiki claims that screens can't be drawn outside of vblank.
You cannot write new data during rendering, no.
Recently, it did not say something like, "screens can't be drawn outside of vblank, unless rendering is disabled." Leaving that bold part off makes it seem like, to me at least, that screens must be drawn during vblank.

Thank you lidnariq and supercat! :D


edit.
final edit.
Last edited by unregistered on Mon May 20, 2019 6:49 pm, edited 1 time in total.

lidnariq
Posts: 8692
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 8x16 and whatever else unreg wants to know

Post by lidnariq » Mon May 20, 2019 6:46 pm

unregistered wrote:So, since there seem to be 61,440 pixels in an entire (not just the visible part of NTSC) NES screen (32x8+30x8==61440) and drawing a screen must take 61440 x .000000182 == 0.01118208 seconds, it must be possible to disable rendering,
The CRT and PPU are both busy between each horizontal line of pixels, so the math is not 256x240 but instead 341x240=81840; 81840x.000000182 = .0149. So, in practice, you only have the 20-ish scanlines between when NMI is asserted and when rendering starts on its own again later, or approximately .0013 seconds.
it would be really cool to see it work without blinking. :)
The only way you're getting that is by either rationing the amount you upload per vblank, or using advanced tricks to turn on rendering late or turn it off early.
unregistered wrote:Recently, it did not say something like, "screens can't be drawn outside of vblank, unless rendering is disabled." Leaving that bold part off makes it seem like, to me at least, that screens must be drawn during vblank.
If you can point where on the wiki it says that, I'd love to fix it.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Mon May 20, 2019 7:09 pm

lidnariq wrote:
unregistered wrote:Recently, it did not say something like, "screens can't be drawn outside of vblank, unless rendering is disabled." Leaving that bold part off makes it seem like, to me at least, that screens must be drawn during vblank.
If you can point where on the wiki it says that, I'd love to fix it.
Hmm... sorry, maybe I read this too fast:
A value of $00 or %00000000 disables all rendering. It is usually best practice to write this register only during vblank, to prevent partial-frame visual artifacts.
In my head I read, "It is usually best practice to write this (info to the PPU) only during vblank, to prevent partial-frame artifacts." I guess I read "this" and thought you were talking about writing info to the PPU bc that's what the wiki was talking about... rendering. Sorry lidnariq, reading is sometimes problematic for me. I will respond, if I have a response, to the rest of your post tomorrow. :)

oh that quote is from https://wiki.nesdev.com/w/index.php/PPU ... rs#PPUMASK

supercat
Posts: 161
Joined: Thu Apr 18, 2019 9:13 am

Re: 8x16 and whatever else unreg wants to know

Post by supercat » Mon May 20, 2019 9:01 pm

unregistered wrote:Hmm... sorry, maybe I read this too fast:
A value of $00 or %00000000 disables all rendering. It is usually best practice to write this register only during vblank, to prevent partial-frame visual artifacts.
In my head I read, "It is usually best practice to write this (info to the PPU) only during vblank, to prevent partial-frame artifacts." I guess I read "this" and thought you were talking about writing info to the PPU bc that's what the wiki was talking about... rendering. Sorry lidnariq, reading is sometimes problematic for me. I will respond, if I have a response, to the rest of your post tomorrow. :)
One may disable rendering at any time during a frame, with the effect that if one doesn't re-enable it, everything from there on down will be blanked. Enabling the PPU during a frame, however, is tricky. The counters are that are used to update the display address while rendering a display are also used to increment the address after each CPU write; consequently, they don't increment while rendering is disabled. As a consequence, if one enables rendering in the middle of the frame, the PPU will show things in the wrong places unless the CPU first loads the counters with correct values, which would in turn require that the CPU know what those correct values should be. Because the correct values of the counters depend upon the position of the beam, which in turn depends on the amount of time elapsed since the end of vertical blank, the only way the CPU can know what values to load into the counters is by knowing how much time has elapsed since vertical blank. There are ways this can be done, but it is generally difficult.

lidnariq
Posts: 8692
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 8x16 and whatever else unreg wants to know

Post by lidnariq » Mon May 20, 2019 9:39 pm

supercat wrote:One may disable rendering at any time during a frame,
Unfortunately, there's some obscure bug with the OAM DRAM controller that causes it to malfunction the next time rendering is enabled, if it's not turned off at the right time. Either we've never figured out exactly what's going wrong, or I've forgotten where it was stated, but on the wiki we've only documented the window in which it's safe to do so. (between x≥192 for lines with no sprites, x≥240 for lines with at least one sprite, and ... the wiki doesn't say what the upper bound is? this thread implies it's 255. Note that although the discussion in that thread makes it sound like the bug due to starting rendering with OAMADDR nonzero, but it persists across writing to OAMADDR and OAMDMA)

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Tue May 21, 2019 10:27 am

lidnariq wrote:
unregistered wrote:So, since there seem to be 61,440 pixels in an entire (not just the visible part of NTSC) NES screen (32x8+30x8==61440) and drawing a screen must take 61440 x .000000182 == 0.01118208 seconds, it must be possible to disable rendering,
The CRT and PPU are both busy between each horizontal line of pixels, so the math is not 256x240 but instead 341x240=81840; 81840x.000000182 = .0149. So, in practice, you only have the 20-ish scanlines between when NMI is asserted and when rendering starts on its own again later, or approximately .0013 seconds.
it would be really cool to see it work without blinking. :)
The only way you're getting that is by either rationing the amount you upload per vblank, or using advanced tricks to turn on rendering late or turn it off early.
Wow, thank you so much lidnariq for correcting my math! :D After reading supercat's and your most recent reply to this thread it seems like the best way to do this would be to disable rendering when x>=192 (while each screen is drawn horizontaly... right?) draw my screen and reenable rendering before vblank. However, when x >=192 doesn't leave much time for screen drawing... so my screen drawing code would have to be sped up (by me), I think... I have to go... to know exactly how much time elapsed since vblank it would require me counting cycles used between end of vblank and the end of me drawing the screen... many of the branches are permanent during this screen drawing so that might not be too bad... then I load that cycle number and write it to somewhere; and then turn on rendering before vbank starts. Seems difficult but, maybe possible? Drawing screens during vblank seems simpler, but then I have to think about redoing my vblank code. Ok, bye, thank you lidnariq and supercat so much! :D

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Wed May 22, 2019 2:58 pm

Mesen is so helpful! :D It seems like, from reading Sour's notes in Mesen's Conditional: :?: at the bottom of the Breakpoint window, each scanline takes 341 cycles. So, since vblank starts at scanline 241, then 241-192=49 ... 49*341=16,709 cycles available to draw the screen outside of vblank... and my screen drawing currently takes 16,832 cycles, which leaves only 123 excess cycles... and we'll have to turn rendering on again so if the screen drawing can be reduced by ~150 cycles then that would be enough? This is so much fun! :)

User avatar
tokumaru
Posts: 11438
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: 8x16 and whatever else unreg wants to know

Post by tokumaru » Wed May 22, 2019 3:38 pm

Keep in mind that there are PPU cycles and CPU cycles... In NTSC, the PPU is 3 times faster than the CPU (i.e. during one CPU cycle, the PPU draws 3 pixels). Make sure you're not mixing the cycle types in your calculations.

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

Re: 8x16 and whatever else unreg wants to know

Post by koitsu » Wed May 22, 2019 4:17 pm

tokumaru wrote:Keep in mind that there are PPU cycles and CPU cycles... In NTSC, the PPU is 3 times faster than the CPU (i.e. during one CPU cycle, the PPU draws 3 pixels). Make sure you're not mixing the cycle types in your calculations.
Reference: https://wiki.nesdev.com/w/index.php/Cyc ... cle_counts -- total number of CPU cycles available in NMI, on NTSC, is 2273. An entire frame -- when the PPU begins drawing one -- takes about 29780 CPU cycles to complete. So the latter is how much time essentially you have for your "main loop", and the former is how much time you have available in NMI.

To further expand on what tokumaru said, with regards to Mesen specifically: in Debugger, there are two fields -- "CPU Status: Cycles" and "PPU Status: Cycle". Note that one is plural, the other singular.

"CPU Status: Cycles" is a 32-bit signed counter, indicating how many CPU cycles have passed since the game was reset. In more recent AppVeyor builds, its been upgraded to a 64-bit signed counter (which is not backwards-compatible with previous save states, just as a comment in passing). I also don't know why this value isn't *unsigned*, but whatever. Edit: Sour and I have discussed this. The number is actually an unsigned 64-bit integer; the Trace Logger documentation says 32-bit signed, AppVeyor commit comments said "64-bit int" (when increasing the size), etc. but it is in fact unsigned.

"PPU Status: Cycle" effectively ranges from 0 to 340, incrementing gradually when/as the PPU draws. It's reset to 0 every frame. Details of what the PPU does during each PPU cycle is available.
Last edited by koitsu on Wed May 22, 2019 5:24 pm, edited 3 times in total.

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Wed May 22, 2019 4:31 pm

Wow tokumaru... ok, so that means we only have around 5,569 cpu cycles to draw an entire screen? And my screen drawing function was just reduced to 16,536 cycles... which, would have been sufficient with my messed up math. Ahh, ok, I guess it's not possible for me to draw blinkingless screens outside of vblank. Maybe I'll try again tomorrow. :)

Thank you koitsu for the info and links... will look at them tomorrow. :)

unregistered
Posts: 1038
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Re: 8x16 and whatever else unreg wants to know

Post by unregistered » Wed May 22, 2019 5:05 pm

tokumaru, thank you so much for teaching me 1 CPU cycle==3 PPU cycles. :)

lidnariq
Posts: 8692
Joined: Sun Apr 13, 2008 11:12 am
Location: Seattle

Re: 8x16 and whatever else unreg wants to know

Post by lidnariq » Wed May 22, 2019 11:25 pm

unregistered wrote:disable rendering when x>=192 (while each screen is drawn horizontally... right?)
No. Screens are drawn from top to bottom. The range of 192<=x<256 is when, within any given scanline, you have to turn off rendering, IF you do, in order for sprites to not be broken the next time rendering turns on.

There's no restriction on which scanline number (Y) you turn off rendering, but it will produce a solid-colored bar at the bottom of the screen.
unregistered wrote:and my screen drawing currently takes 16,832 cycles,
The entire amount of time the CPU has per redraw, regardless of whether the PPU is drawing, is 341*262/3 ~~ 29780. Your code needs to be a lot faster for "only letting the PPU draw part of the time" to be an adequate solution.

I'd strongly recommend figuring out how to divide uploads across multiple refreshes. You're going to need it anyway.

Post Reply