write to vram - in c problems

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

tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: write to vram - in c problems

Post by tepples »

[ot]
The difference between enabling during prerender and enabling after start of picture is that as long as rendering is reenabled before x=304 of the pre-render line, no special "skinny" address write sequences are needed to set the scroll position.
[/ot]

Anyway, unless you're updating a LOT of video memory at once (CHR RAM animation, rapid scrolling, sub-screen scrolling, or FMV playback), you shouldn't need to worry about micro-optimizing video memory updates yet. You probably aren't gonna need it right now, and when you do, let us know.
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: write to vram - in c problems

Post by Movax12 »

I need all I can get, to a point. The game I was working on could run even better with more write time. Feel free to split to a new thread.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: write to vram - in c problems

Post by tepples »

A clean split isn't possible because of too many posts dealing with both topics. I've summarized the discussion so far to this post.

Now back to your regularly scheduled "write to vram - in c problems".
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

don't worry about it guys, it wasn't really that OT. I was turning the ppu off/on because that's the only way shiru's vram_write works.

another odd thing I noticed vram_put is displaying similar odd behavior (making the screen scroll to where I write to) when I compile some of my old code with the new version of neslib. the code worked fine in the old version. might be my version of cc65.
Wish shiru would mention what version he used, or link it or something.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: write to vram - in c problems

Post by tokumaru »

DrDementia wrote:(making the screen scroll to where I write to)
This is a symptom of not resetting the scroll after writing/reading to/from PPU memory. See, the internal address register programs use to access PPU memory is the same one the PPU uses when reading its own memory for rendering images, so rendering will start from wherever that register points to when rendering starts. After you're done updating VRAM, you should always set the scroll to the place where you want rendering to start from.
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: write to vram - in c problems

Post by rainwarrior »

The problem, I think, is with the implementation of ppu_on_all().

Code: Select all

_ppu_on_all:
	lda <PPU_MASK_VAR
	ora #%00011000
ppu_onoff:
	sta <PPU_MASK_VAR
	sta PPU_MASK
	jsr _ppu_waitnmi
	lda #$00
	sta PPU_ADDR
	sta PPU_ADDR
	lda <PPU_CTRL_VAR
	sta PPU_CTRL
	rts
Please correct me if I'm wrong in this analysis, but this turns on rendering immediately, which means it might happen in the middle of a frame somewhere, giving you half a blank screen and half of an incorrectly scrolled screen for the first frame it is turned on. Next it waits for an NMI to complete and immediately sets the VRAM address to 0, which will force the scroll to 0,0 for the second frame (unless the NMI routine is finished before the end of vblank -- this might depend whether or not music is playing). It will only start applying your scroll correctly on the third frame, as far as I can tell.

The purpose of ppu_off() and ppu_on_all() is generally to leave rendering disabled for an extended period of time (i.e. multiple frames) while you make some changes to the nametable (direct vram writes). If you're only turning off rendering occasionally, the two frames of incorrect apperance might not be a big deal, and for a game where the scrolling is supposed to be at 0,0 anyway, you're only talking about one frame of incorrect appearance.

You may want to remove these 3 lines from _ppu_on_all:

Code: Select all

	lda #$00
	sta PPU_ADDR
	sta PPU_ADDR
These lines serve no purpose, as the correct scroll will already get applied during the line: jsr _ppu_waitnmi

This should cut the incorrect visual down to a single half-rendered frame.


In the examples he provided, this half-rendered frame seems to be hidden by an all-black palette. The new palette doesn't get applied until the _ppu_waitnmi subroutine, so the bad frame is not seen. The second problem frame is also not an issue since all the examples start at 0,0 scroll anyway. This might explain why _ppu_on_all does not appear very robust; in the way shiru was using it, there really is no problem to be seen. You could hide the problem yourself by clearing the palette, and rendering one frame before calling ppu_off():

Code: Select all

pal_clear()
ppu_waitnmi()
ppu_off()
// ... do your vram writes here
// ... setup your new palette
ppu_on_all()
This adds an extra frame of latency to your turning off the PPU (probably negligible), but should hide the half-rendered frame.
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

tokumaru wrote:
DrDementia wrote:(making the screen scroll to where I write to)
This is a symptom of not resetting the scroll after writing/reading to/from PPU memory. See, the internal address register programs use to access PPU memory is the same one the PPU uses when reading its own memory for rendering images, so rendering will start from wherever that register points to when rendering starts. After you're done updating VRAM, you should always set the scroll to the place where you want rendering to start from.
so say I write to 0x2180 after that I should set the scroll back to 0x2000 where my nametable starts and was loaded to. like this?
vram_adr(0x2000);


where's that register located in memory, maybe I can use a debugger and watch that spot, that may help me understand what's going on.

@RW I 'm going to test some stuff out and reply to your post.
thanks guys for trying to help me figure out this out. it's annoying me a bit I can't get this to work correctly.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: write to vram - in c problems

Post by tokumaru »

DrDementia wrote:so say I write to 0x2180 after that I should set the scroll back to 0x2000 where my nametable starts and was loaded to. like this?
vram_adr(0x2000);
I can't say anything specific to programming in C, because I only program in assembly, but the correct way to (re)set the scroll is not to manipulate the address register directly, but using the registers that are actually meant to control scrolling: $2000 (name table selection) and $2005 (pixel scroll within the selected name table). The library you're using should provide a way to set the scroll through $2000 and $2005, you should look for that.

The address register should only be manipulated for scrolling purposes when changing the scroll OUTSIDE of VBlank, like is done for status bars and parallax effects, which I'm pretty sure is not your case.
where's that register located in memory, maybe I can use a debugger and watch that spot, that may help me understand what's going on.
This register is internal to the PPU and you can't watch it by looking at memory addresses. The emulator has to show you its value. I think FCEUX's debugger shows you the current VRAM address, others might too.
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

tokumaru wrote:the correct way to (re)set the scroll is not to manipulate the address register directly, but using the registers that are actually meant to control scrolling: $2000 (name table selection) and $2005 (pixel scroll within the selected name table).
so looking at this page
trying to get a better understanding of how this works.

And shiru's "vram_adr" does this

Code: Select all

_vram_adr:
	stx PPU_ADDR
	sta PPU_ADDR
	rts
and he has PPU_ADDR defined as $2006. which matches the wiki, but what's in x,a? the example on the wiki of writing to $2006 makes a little more sense

Code: Select all

   lda #$21
  sta PPUADDR
  lda #$08
  sta PPUADDR

here $21,$08 are getting loaded into a and then stored to PPUADDR (upper byte first)
tokumaru wrote: This register is internal to the PPU and you can't watch it by looking at memory addresses. The emulator has to show you its value. I think FCEUX's debugger shows you the current VRAM address, others might too.
FCEUXD shows a,x,y but I didn't see the current vram address anywhere. might be there somewhere though
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: write to vram - in c problems

Post by rainwarrior »

FCEUXD is really old, I suggest getting the latest FCEUX. I don't know what the debugger looks like in FCEUXD, but here's where to find the VRAM address in FCEUX 2.2.2
Attachments
FCEUX_debug_vram_address.png
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: write to vram - in c problems

Post by tepples »

In FCEUX 2.2.0, I've run into problems where PPU:, Scanline:, and Pixel: don't update properly when I step through a program. Is this fixed in the latest version?
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: write to vram - in c problems

Post by rainwarrior »

They're all working fine for me in 2.2.2 so possibly it's been fixed?
Post Reply