[Notes I made while debugging pNES.  Unedited, so don't laugh.]

Nestra proper seems to run Zelda at 35-40 fps at the beginning.
With 3dfx enabled it's 10-20 fps, don't know why the (internal) discrepancy.

3dfx stupid mode (i.e., reloading every texture every single frame)
seems to do about 30 fps.

-- test rendering speed 11/18 --

This is without any kind of display whatsoever, just 6502 core emulation:
frames: 40222Time: 10.93 s  Frames: 40222  FPS: 3681.31  TPF: 0.27 ms

This is X11_DISP (render tiles to pixmap) enabled.
frames: 866Time: 12.60 s  Frames: 866  FPS: 68.74  TPF: 14.55 ms

This is X11_DRAW enabled.
frames: 903Time: 9.74 s  Frames: 903  FPS: 92.74  TPF: 10.78 ms

This is X11_DRAW and X11_DISP.
frames: 576Time: 15.45 s  Frames: 576  FPS: 37.28  TPF: 26.82 ms 

This is GLIDE_BG.
Time: 10.63 s  Frames: 444  FPS: 41.77  TPF: 23.94 ms

This is GLIDE_SPRITES (but note there's no screen clear).
Time: 13.43 s  Frames: 801  FPS: 59.66  TPF: 16.76 ms

This is GLIDE_BG and GLIDE_SPRITES.
Time: 14.88 s  Frames: 580  FPS: 38.97  TPF: 25.66 ms

-- end rendering speed 11/18 --

-- test rendering speed 11/28 --
(walking right one screen immediately, then waiting 5 seconds, zelda)

This is GLIDE_BG.
Time: 8.14 s  Frames: 1027  FPS: 126.18  TPF: 7.93 ms

This is GLIDE_SPRITES.
Time: 6.53 s  Frames: 1125  FPS: 172.36  TPF: 5.80 ms

This is GLIDE_BG and GLIDE_SPRITES.
Time: 8.06 s  Frames: 730  FPS: 90.57  TPF: 11.04 ms

This is no display and walking as above:
Time: 7.60 s  Frames: 17826  FPS: 2346.14  TPF: 0.43 ms

No display standing there for 10 seconds
Time: 10.45 s  Frames: 30601  FPS: 2927.20  TPF: 0.34 ms

-- end rendering speed 11/28 --

11/28 GLIDE_BG+SPRITES with SKIP_OFFSCREEN_SPRITES:
Time: 7.39 s  Frames: 913  FPS: 123.55  TPF: 8.09 ms

---

Tiles have 4 bits of color for each pixel, 2 of which reside outside the
tile (in attribute memory or sprite memory).  This means the tile colors
could be updated at any time without rewriting the tile data (i.e.,
characters from CHR-ROM mapped into the Pattern ?Memory can be
displayed in different colors despite the fact that they can't be
rewritten, even without changing the palette).  Since it would be
inefficient to reload texture memory every time attributes changed,
I propose that 4 textures be maintained, one for each possible "outside"
color. (q.v. line 40, nestra/x11.c?)

Problem is, every time a palette color is modified, all the textures
containing that color have to be reloaded anyway.  And that's a lot
of textures if we use 4 for each tile. ...  Palette management
could be a big problem.  (What if 3dfx's palette mode is used?  Do i
even have TMU rev >1.0?)

If necessary we could use depth buffer to redraw tiles behind
already-drawn sprites, or vice versa.

Textures will obviously have to be reloaded after PPU pattern memory is
accessed, but we don't want to reload until after the accesses finish ...
my guess is, we can either (1) rely on accesses to occur in spurts (that
is, one write to the index address and several writes to the data write
address), and figure out how to detect when a spurt ends, or (2) assume
these updates can only occur during a blanking period, and if access(es)
were detected during the blank, then update only the touched textures at
the /end/ of the blanking period, since nothing could have been drawn
between the access time and the end of the blank. (2) seems more
reasonable.

Is the emu drawing each scanline as it comes it, or just drawing the
entire screen in one shot, after a predetermined number of instructions?
UpdateDisplay called at io.c at line 301 from donmi.
NMI is generated by each refresh (VBlank).
But video memory can only be written during the vblank--so why does nmi
refresh the screen--this would indicate nothing can run during the vblank
ok, see part of it--need to refresh during vblank b/c "refresh" is just
writing to our video card memory, then our video card does the scanline
painting on its own after vblank--maybe nmi doesn't actually occur
during the nes's scanline vblank period

Looks like this is an entirely line-based engine.  Only seeming obstacle
to tile-based is the fact that VRAM address can be changed in mid-HBlank
(like Squaresoft games do) rather than only mid-VBlank to implement
partial vertical scrolling.  Oh, also hscroll register is read at start of
every scanline ;(.  Fortunately, VRAM contents (inc. palette) can't be
changed except during VBlank, afaik.


drawimage() draws from whatever clock you last called it with (or 0, if a
new frame occurred) to whatever clock you now call it with.  It's called
to either draw a full frame, or to draw a partial when something changes
that's going to affect the rest of the frame -- for example, an hscroll
change or Sprite DMA in mid-frame.  "NMI" appears to occur /sometime/ after
vblank starts so the screen can be transferred to video card memory; it
calls UpdateDisplay which calls drawimage(ENTIRE_SCREEN), so the remaining
image is drawn.


-------------


12/17

vscroll in zelda:
when scrolling up, the alternate screen (0x2400) is filled with the map
that we came from, minus the status bar--i.e. the map starts at row 0
and there is a status-bar-sized hole at the bottom of the screen.  Then
the scroll commences.  As the scroll proceeds, the main screen 0x2000
is filled with the new map from the bottom up--including the status bar
on top.  By the time scroll finishes, main screen 0x2000 contains a full
picture of the map.

During start screen scroll up, the start screen is drawn from the bottom
up on the alternate screen.

During scroll down, it's just like scroll up except main screen is painted
from the top down.

Vscroll was substantially fixed; but at beginning and end still screen is
only drawing partially, it looks like vline is being reset to zero by a
read from 2007, even though it should not be.

------------

1/2/00

added compensation for vscan at beginning of frame (i.e., 2005 is written
during VBL and vscrollreg is modified).  Zelda title now scrolls smoothly,
but bg is one frame behind sprites.  I believe scrolling should be:
(frame) scroll sprites & bg
(frame) idle
(frame) scroll sprites & bg
(frame) idle

but it's currently
(frame) scroll sprites
(frame) scroll bg
(frame) scroll sprites
(frame) scroll bg

Don't know what the problem is.


vmirr: 2 (2800) mirror of 0 (2000); 3 (2c00) mirror of 1 (2400)
hmirr: 1 (2400) mirror of 0 (2000); 3 (2c00) mirror of 2 (2800)

hvmirror is 0 during hscroll; 1 during vscroll (inc start screen) and 1 at
all other times.


1/4/00

vscroll jumping fixed except for the one-frame-behind problem (see cvs log pixels.c r1.7 for
explanation of vline fix).  Sprite display deferred to end-of-frame (previously, displayed every
time the render function was called, which could be several times per frame).
Palette still gray for a few frames at beginning of Metroid, why is this.


1/5/00

Saw the reappearing sprite thing after the character select in zelda... actually, are those sprites
or bg?  If bg, could be same palette update problem as we've seen.

Occasionally sprites (bg?) is slightly off, c.f. scrolling title items in zelda and platforms in 1-2
mario.

smb3--sprites are garbled halfway down--like wrong pattern table page is being read.


palette gray at beginning of faxanadu--at title screen, permanently, which means I suppose that palette
isn't being read or stored correctly at very beginning, until a palette update.  Looks like 3f00 is
being written ahead of time...  main game was also blank ... palette issue fixed, main game ok, title
ok

loads tiles 256-512 with correct colors, palette is updated 1 frame before--we should check the actual
palette values for accuracy...

in spelunker, vscroll makes one line at the top be incorrect--which looks like a tile read error,
not a display error, because the height of the line changes with the vscan amt.

in rambo, some letters in the dialogues are odd colors

zelda2 is slow on overhead map, also offset is screwed up.  Also palette errors, fixed by off-by-1
solution.

rad racer is unplayable, offset is completely weird

note: palette[0-24] is not linear list of numbers

still don't understand why palette_24[0] is 0x3f3f3f...

culprit: palette[] array isn't set from palette_24 right away (i.e. palette[] is updated after
the cache misses)

0x3f00 is being written to at clock > 81840 (about 85000).




nestra

non-vram registers are updated several times; drawimage is called, partial image drawn offscreen
update_display is called by donmi at VBL (endclock == 81840)
	drawimage(81840) called by update_display
	update_colors called by update_display
palette (vram) is updated after VBL (endclock > 81840)
    drawimage is called every time: immediate exit, since endclock > 81840
clock starts over at 0; no register updates this time, nothing happens till VBL
update_display is called by donmi at VBL (endclock == 81840)
	drawimage(81840) called by update_display
	update_colors called by update_display, updating palette -- but we rendered a frame already

It seems, then, that palette updates are always 1 frame behind

Yep.  Although registers are updated during VBL, the palette isn't copied until the next frame, since
update_display (and hence update_colors) doesn't get called until VBL occurs again.

Since update_display gets called before update_colors can update the palette
from last time, pnes tiles are loaded into cache with a palette that's one
frame behind, so tiles are always one palette switch behind.

For nestra no effect is noticable because the "tiles" (scanlines) are built
from scratch every time they are rendered, so the next frame the palette will
be correct.  There's just a 1 frame delay there.

How to fix?  palette array needs either to be updated every time a palette entry is modified (stupid),
or modified the first time drawimage is called after a VBL.  We can't update it the first time
update_display is called after a VBL, because an intervening register update may occur before VBL,
and drawimage will be called and load tiles with the old palette.  Solve: if curclock == 0 and
endclock <= 81840, this is guaranteed to be the first time we're called, so we call update_colors.
This seems to work.

----

Metroid has a lot of cache misses--because palette updating often.  Gotta fix that (hard).

Still get those sprites over the bomb and key when scrolling in Zelda

in faxanadu, when screen fades out (you die) the P in upper left remains

in smb3, after fixing the off-by-1 palette issue above, the sprites no longer appear in the game
-- note: in orig nestra, left and right sides of screen (1 tile width) have incorrect colors.

sprite behind doesn't work

looks like gauntlet uses special 4 page vram thing

olympus plays very well, though scrolling is subject to an offset problem (the same problem in Zelda2,
I suspect)

contra seems to play very well

destiny plays well; top & bottom line on vscroll is still screwed up.

strange--in both dn and nestra, walking right with Link in Zelda2 and then immediately holding left
causes you to slide uncontrollably.

---

1/9/00

Rightmost and leftmost tiles during hscroll are incorrect in OLYMPUS, Zelda2.  nestra has the
same problem.

zelda2 seems to stutter occasionally during hscroll on overhead map; supposed to scroll 1 pel/frame,
but frame-by-frame shows that hscroll sometimes doesn't increment in certain frames ???

occasionally a frame

2/2/00

Fixed Metroid weirdness with jumping sprites that were vflipped; was incorrect handling of vflipped
8x8 sprites.  However incorrectly drawn remain with Zelda2!!! But it's not a VFLIP problem. 
Solved: odd sprite tiles need to be stripped of their oddness (logical AND with ~1) since they reference
odd pattern table.  As a bonus, Zelda1 behaves better w/r/t sprites appearing during hscroll, but
bomb still appears as brown.  Believe this will be solved with "behind" processing.

Sprites are still screwed up in SMB3, but somewhat better now.

During certain games (Labyrinth, et al) top scroll wraps to bottom (or vice versa).

Leftmost column wrong (Zelda2, Double Dragon).

Mystery Quest scroll screwed up.  Chubby Cherub in the same way.

----

2/5/00 

PPU Control 2 BG and Sprite Clip bits are now handled via hardware clipping, less than ideal, but
the cleanest implementation.  Olympus completely fixed, Zelda 2 almost fixed but depending on the
y scroll value up to half of the leftmost couple of pixel columns display incorrect data during
scroll.  Need to go up for a bit and walk right to see this. Also, Zelda 2 appears to be blocking
out the right 8 pixels to compensate for the left 8 hardware blocked pixels, using a column of
opaque sprites, I think.  But the topmost (y==0) row of pixels show thru, don't know why. */

Appears that Zelda2 puts the sprites starting at y==1, continuing every 16 pixels ending with y=225;
makes more sense to start at zero.  We're adding 1 to the actual y-coord byte in SPR-RAM because
that's usually correct; maybe sometimes we're not supposed to add 1?

U4 has gray strip along left side.  Probably related to the BG Clip bits.  U3
has horiz scrolling artifacts (esp sprites) in towns.

-----

2/16/00

Simple behind processing implemented using the depth buffer.  Note that I'm not sure how overlapping
sprites will react--see code comment.

Not sure when this happened, but RIVCITY now has flashing brown bar in left column.
Clipping problem?  Yes, clipping problem.  See code comment.  Works correctly only if full
bg color does not change at some point when bg clip is active.

OLYMPUS isn't fixed anymore!  Was it ever?

2/18/00

Still: top and bottom scrolling row is wrong; left and right scrolling col is wrong.
Both nestra and dn have the top/bottom thing too.  Happens with many games: Labyrinth, Ff1e, 
destiny, FARIA.  left-right: megaman6, olympus, ...

Zelda2 is actually quite fast on overhead map in top left corner; when move to middle,
gets slower. ??

As I thought, rendering two objects with the same Z value, overlapping, omits the second
one.  Why does overlapping sprites work then?

In CVANIA when you walk in front of a candle, it flickers

Major problem: in SMB3, calls mapper I believe during HBL but not VBL, so contents of
CHR-RAM can change out from under us.  No good solution to this problem.  The cache
becomes invalid if VROM is swapped out, but we don't check for this contingency.  If we
invalidate whole cache at this time, it's worse than having no cache at all.  Possible
solutions: store ALL of cart's swappable VROM pages in the card (too much memory); store a
few swappable pages in the card (possible, but each nes tile takes 512b in the Voodoo (8h
x 8w x2 byte/pel x4 colors) so we only have space for 4,096 tiles in 2MB texture memory,
which is 64K of VROM).  Note we can save card memory by not saving room for all four
colors for each tile, since all four are rarely used; it would require more advanced
algorithms and a more involved mapping function from tile to voodoo memory than the
current (tile_start + tile_size * (tilenum * colors_per_tile + color)).  And a memory
arena like malloc's, and ...  Actually not true, just a free-space pointer list.  And an
LRU function, and ...  Could save more memory by switching to 8-bit textures.  Also the
thought of palettized textures.  Problem for sprites though; we only draw them at the end
of the frame, because I didn't realize they could change mid-frame.  We might have to run
thru all 64 sprites every time, drawing only the ones that fall within the bounds.
Question is, can they change mid-sprite??

Or we treat each tile, no matter on which page, as a separate cacheable entity and forget
about swapping pages; we just need to keep track of each individual tile's position in
VROM.
