It is currently Sun Aug 25, 2019 6:10 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: Sun May 11, 2014 9:47 am 
Offline
User avatar

Joined: Fri Oct 14, 2011 1:09 am
Posts: 248
I took the time and used the venerable Visual2C02 to trace through 1.2 complete frames and see what kind of signal the PPU pushes out at all times.

Here's my results.

First, some terminology.
There are twelve signals that the PPU can produce. Some of those are identical. I will call them by the name that Visual2C02 uses.

  • vid_sync_l and vid_sync_h: aka. Sync and Black.
  • vid_burst_l and vid_burst_h: Colorburst low and high.
  • vid_luma0_l and vid_luma0_h: Signal levels equivalent to colors 0D and 00 respectively.
  • vid_luma1_l and vid_luma1_h: Signal levels equivalent to colors 1D and 10 respectively.
  • vid_luma2_l and vid_luma2_h: Signal levels equivalent to colors 2D and 20 respectively.
  • vid_luma3_l and vid_luma3_h: Signal levels equivalent to colors 3D and 30 respectively.
  • vid_luma3_h is identical to vid_luma2_h.
  • vid_sync_h is identical to vid_luma1_l.
Additionally, there is a vid_emph which can vary the vid_luma* signal output.

So here's a scanline-by-scanline analysis of what the PPU produces.

  • hpos=4: On lines 0―239, the PPU starts producing color image (or grayscale image if $2001.0 was set).
  • hpos=257: On lines 245―247, the PPU switches to vid_sync_h here. (Equalization pulses)
  • hpos=260: On lines 0―239, the PPU starts producing background color again. (As on hpos=330.)
  • hpos=271: On lines 0―241, the PPU switches to vid_sync_h here. (Front porch)
  • hpos=280: On every line, the PPU switches to vid_sync_l here. (Horizontal sync)
  • hpos=305: On lines 0―243 and 247―261, the PPU switches back to vid_sync_h here. (Begin of back porch)
  • hpos=309: On lines 0―243 and 247―261, the PPU starts producing colorburst signal.
  • hpos=324: On lines 0―243 and 247―261, the PPU switches back to vid_sync_h here. (End of back porch)
  • hpos=329: On lines 0―240 and 261, the PPU starts producing background color in grayscale as if $2001.0 was set. This serves as the "pulse" that signifies the beginning of the image, as it is always different from the vid_sync_h in back porch.
  • hpos=330: On lines 0―240 and 261, the PPU starts producing background color normally.
The signal switches always happen exactly 4 half-cycles after the horizontal position (hpos) has been incremented.

Corollaries:
  • On scanlines 0―241, the PPU produces color image. This means 242 lines of image. The palette background color is rendered on all of them.
  • On lines 242―244 and 248―261, the PPU produces long black lines (297 columns worth vid_sync_h). These black lines include the colorburst and sync as normal visible lines do, but they do not include the "pulse".
  • On lines 245―247, the PPU produces very long sync pulses (318 columns).

Colorburst signal is signal that toggles vid_burst_l and vid_burst_h after every 6 half-cycles.
Colors are produced as such (this is just a rehash of the information on http://wiki.nesdev.com/w/index.php/NTSC_video):
  • For colors $00,$10,$20,$30 (i.e. $X0), only vid_lumaX_h is produced.
  • For colors $0D,$1D,$2D,$3D (i.e. $XD), only vid_lumaX_l is produced.
  • For colors $XE and $XF, only vid_luma1_l is produced (i.e. treated as $1D; X is ignored).
  • When grayscale is active, any color $XY is treated as if $X0, even if Y=D.
  • For any other color $XY, vid_lumaX_l and vid_lumaX_h are alternated every 6 half-cycles with starting phase Y relative to colorburst.

Missing tests:
  • I did not test whether the emphasis bits affect the background color or any other signals.

Source material:
Code:
Making the golden log:

http://www.qmtpro.com/~nes/chipimages/visual2c02/

Find "vid"
Select Post-render scanline, odd frame
Unclick Show sprite RAM contents
Unclick Animate during simulation
Trace these too: vid,vid_sync_l,vid_sync_h,vid_burst_l,vid_burst_h,vid_luma0_l,vid_luma0_h,vid_luma3_l,vid_luma3_h
Click RESET
Hide Chip Layout
Poke at 3F00: 3D (this causes SPIKE to be vid_luma3_h, BORDER to be vid_luma3_l, and GAME to be vid_luma0_h)
Poke at 0000: 16 * FF (ensures that game view will be rendered at color 00 rather than 3D)
        NEXT SCANLINE
After every 3 scanlines or so, CTRL-A to mark everything, and paste it into a text file.
Clear log AND DON'T FORGET TO CLICK "Trace These Too" again!
The simulator becomes linearly slower and slower the longer the log is, so you have to clear it periodically.
Note: If you have to reset, you MUST poke the palette value again!

---
Signalwise summary:
  vid_luma0_h (Game) at x=  4 on lines 0-239
 vid_sync_h  (Black) at x=257 on lines 245-247
vid_luma3_l (Border) at x=260 on lines 0-239
 vid_sync_h  (Black) at x=271 on lines 0-241
  vid_sync_l  (Sync) at x=280 on lines 0-261
 vid_sync_h  (Black) at x=305 on lines 0-243, 247-261
 vid_burst_* (Burst) at x=309 on lines 0-243, 247-261
 vid_sync_h  (Black) at x=324 on lines 0-243, 247-261
 vid_luma3_h (Pulse) at x=329 on lines 0-240, 261-261
vid_luma3_l (Border) at x=330 on lines 0-240, 261-261
---
Linewise summary (each "line" begins at column 280 on _previous_ scanline):
  Line 240
    [[ These six lines are manual simulation; extrapolation from next frame. ]]
    row 239, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle -242
    row 239, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle -142
    row 239, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle -126
    row 239, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle -66
    row 239, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle -46
    row 239, column 330, half-cycle 4:   vid_luma3_l (Border) (282 columns) - cycle -42
   
    [[Simulation begins here, using the "Post-render scanline, odd frame" option in Visual2c02.
      These two first lines are garbage.]]
    row 240, column   0, half-cycle 0:   vid_sync_h  (Black)  (1.5 columns) - cycle 0
    row 240, column   1, half-cycle 4:   vid_luma3_l (Border) (270 columns) - cycle 6

    row 240, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 1086
    (341 cycles)
  Line 241
    row 240, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 1122
    row 240, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 1222
    row 240, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 1238
    row 240, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle 1298
    row 240, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle 1318
    row 240, column 330, half-cycle 4:   vid_luma3_l (Border) (282 columns) - cycle 1322
    row 241, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 2450
    (341 cycles)
  Lines 242-244
    row 241, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 2486
    row 241, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 2586
    row 241, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 2602
    row 241, column 324, half-cycle 4:   vid_sync_h  (Black)  (297 columns) - cycle 2662
    (341 cycles)
  Lines 245-247
    row 244, column 280, half-cycle 4:   vid_sync_l  (Sync)   (318 columns) - cycle 6578
    row 245, column 257, half-cycle 4:   vid_sync_h  (Black)   (23 columns) - cycle 7850
    (341 cycles)
  Lines 248-261
    row 247, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 10670
    row 247, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 10770
    row 247, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 10786
    row 247, column 324, half-cycle 4:   vid_sync_h  (Black)  (297 columns) - cycle 10846
    (341 cycles)
  Line 0
    row 261, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 29766
    row 261, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 29866
    row 261, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 29882
    row 261, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle 29942
    row 261, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle 29962
    row 261, column 330, half-cycle 4:   vid_luma3_l (Border)  (14 columns) - cycle 29966
    row   0, column   4, half-cycle 4:   vid_luma0_h (Game)   (256 columns) - cycle 30022
    row   0, column 260, half-cycle 4:   vid_luma3_l (Border)  (11 columns) - cycle 31046
    row   0, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 31090
    (340 cycles; column 0 was skipped)
  Lines 1-239
    row   0, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 31126
    row   0, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 31226
    row   0, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 31242
    row   0, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle 31302
    row   0, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle 31322
    row   0, column 330, half-cycle 4:   vid_luma3_l (Border)  (15 columns) - cycle 31326
    row   1, column   4, half-cycle 4:   vid_luma0_h (Game)   (256 columns) - cycle 31386
    row   1, column 260, half-cycle 4:   vid_luma3_l (Border)  (11 columns) - cycle 32410
    row   1, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 32454
    (341 cycles)
  Line 240-241
    row 239, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 357122
    row 239, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 357222
    row 239, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 357238
    row 239, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle 357298
    row 239, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle 357318
    row 239, column 330, half-cycle 4:   vid_luma3_l (Border) (282 columns) - cycle 357322
    row 240, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 358450
    (341 cycles)
  Lines 242-244
    row 241, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle
    row 241, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle
    row 241, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle
    row 241, column 324, half-cycle 4:   vid_sync_h  (Black)  (297 columns) - cycle
    (341 cycles)
  Lines 245-247
    row 244, column 280, half-cycle 4:   vid_sync_l  (Sync)   (318 columns) - cycle
    row 245, column 257, half-cycle 4:   vid_sync_h  (Black)   (23 columns) - cycle
    (341 cycles)
  Lines 248-261
    row 247, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 368034
    row 247, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 368134
    row 247, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 368150
    row 247, column 324, half-cycle 4:   vid_sync_h  (Black)  (297 columns) - cycle 368210
    (341 cycles)
  Lines 0-239
    row 261, column 280, half-cycle 4:   vid_sync_l  (Sync)    (25 columns) - cycle 387130
    row 261, column 305, half-cycle 4:   vid_sync_h  (Black)    (4 columns) - cycle 387230
    row 261, column 309, half-cycle 4:   vid_burst_* (Burst)   (15 columns) - cycle 387246
    row 261, column 324, half-cycle 4:   vid_sync_h  (Black)    (5 columns) - cycle 387306
    row 261, column 329, half-cycle 4:   vid_luma3_h (Pulse)    (1 columns) - cycle 387326
    row 261, column 330, half-cycle 4:   vid_luma3_l (Border)  (15 columns) - cycle 387330
    row   0, column   4, half-cycle 4:   vid_luma0_h (Game)   (256 columns) - cycle 387390
    row   0, column 260, half-cycle 4:   vid_luma3_l (Border)  (11 columns) - cycle 388414
    row   0, column 271, half-cycle 4:   vid_sync_h  (Black)    (9 columns) - cycle 388458
    (341 cycles)


Top
 Profile  
 
PostPosted: Wed May 21, 2014 3:38 pm 
Offline
User avatar

Joined: Fri Oct 14, 2011 1:09 am
Posts: 248
I updated the previous post, now including double-checked content based on tracing through an entire frame and a little more.

Additional notes:

- If rendering is disabled ($2001 is $00), the cycle skipping (column 0 of row 0) does not happen. Then line 0 is always 341 columns long.

- If sprite rendering is enabled, even though background rendering is not ($2001 is $10), the skipped cycle still happens.

- If background rendering is disabled, background color (Border) will be rendered instead of Game content where applicable. Practically these scanlines will be rendered the same way as scanline 240.

- The 8-pix border flags do not have any effect if the corresponding rendering-enable flag is disabled. This means that $2001.1 is only checked if $2001.3 is set, and $2001.2 is only checked if $2001.4 is set. This also means that if $2001 is $06, it is the same as if $2001 was $00.

- None of these bits change the vblank region in any manner (except for the skipped cycle).

- The grayscale bit is always honored, regardless of the other enable-disable flags. It affects the rendering of border, even on scanlines 240-241. (The Pulse will always be generated as if grayscale was enabled, regardless of its actual state.) I assume that the de-emphasis bits are always honored too. I have not tested it though.

Testing the different rendering enable/disable flags was done by adding an option "?c=2100" into the URL; where 21 stands for port $2001 and 00 stands for the value $00 to be written into that port.


Top
 Profile  
 
PostPosted: Fri Dec 12, 2014 9:34 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 3141
Location: Tampere, Finland
Since this topic came up at #nesdev, and I was a bit bored, I wrote a small Python script to generate a visual representation of the PPU signal layout:
Attachment:
nes-ppu-render-layout.png
nes-ppu-render-layout.png [ 939 Bytes | Viewed 1934 times ]

Here's the same image shifted right 70 pixels, so that the front porch is at the left side of the image (PPU counter 0,0 is at 70,0 in image):
Attachment:
nes-ppu-render-layout-shifted70.png
nes-ppu-render-layout-shifted70.png [ 923 Bytes | Viewed 1934 times ]

Key: blue = border, red = active, light gray = sync, green = colorburst, dark gray = "pulse" (in wiki table terminology)

Images are based on info from: http://wiki.nesdev.com/w/index.php?titl ... oldid=9006. If you notice any mistakes, lmk.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot] and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group