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

DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

write to vram - in c problems

Post by DrDementia »

I have question about writing to vram where my nametable is (0x2000). I'm exploring shiru's neslib and programming in c.

I want to update the vram and I tried various methods, here's some code for you guys

Code: Select all

     
             ppu_waitnmi();
             ppu_off();  
             vram_write((unsigned char*)array16,address,16);
             ppu_on_all(); 
If I write 16 bytes to vram I get a graphic glitch. I can write 15 bytes or less without the glitch though with this method.
Not sure if it's a timing or speed issue. maybe I'm trying to do things improperly(bad code).

I really want to change multiple spots in vram then render. what's the right way to do this?
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 »

When you say you get a glitch, do you mean you get a bit of black at the top of the screen and the image is shifted down? What is the glitch?

The vblank period after NMI is a very short time, and it is really difficult to do very much at all in C code during this time. The NMI handler in shiru's library is probably already doing a bunch of things (uploading sprites, etc.) and should have a special way of uploading nametable data during vblank. So, after it's done all that, there's probably not much time left for you to do any manual uploads of your own.

You should only need to turn the PPU off and on manually when you are going to turn rendering off for a long time to do a lot of PPU uploading, like if you're setting up the whole screen at once.


Edit: I think what you need to use is the "set_vram_update" function, which you should do before ppu_waitnmi(), and your update will automatically be applied during the ppu_waitnmi() call.
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

thanks for the help.
The glitch seems to fill the whole screen with garbage for a frame. here's some more code to show what's happening.
http://pastie.org/8964484

you should be able to compile that. it's a minimal example of what I was trying to do. I'll look at "set_vram_update" maybe that will work. I did notice you could use it during rendering, but it said "number of transferred bytes is limited by vblank time"

the other vram functions "works only when rendering is turned off" according to shiru, which is why I was turning the ppu off/on.

I'm probably trying to do things in a weird way.

edit: added "delay(20);" to the loop so you could see the glitch easier. and attached the compiled .nes for anyone to test.
Attachments
vram_write.zip
(3.69 KiB) Downloaded 154 times
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 »

Oh, that's interesting. The glitch frame you are seeing is that occasionally for 1 frame you're using the wrong CHR pattern page for your nametables.

This is controlled by bit 4 of the register at $2000. Once every several frames your code is writing $80 instead of $90 to this register, which causes it to select the $0000 CHR page for backgrounds instead of the $1000 page you want.

I don't know how this is being triggered, or why it doesn't happen every frame. The code is a LDA #$80, STA $2000, which I can't find in the neslib.s source found here. Maybe shiru can answer your question.

However, the code you have written is still a problem. You should only turn the PPU off when you need to take rendering down for multiple frames so you can place a lot of data into the PPU. For an update that happens every frame, do not turn the PPU off, just push the data through with set_vram_update. You should be able to push at least 32 bytes per frame through there, if not more (I don't use shiru's neslib, so I can't tell you its performance limits).


Edit: oh, didn't see your comment about delay(), I was going by your pastebin source. That explains why it's not every frame at least. I expect the offending write to $2000 is in ppu_on_all, but I also think you are probably using an out of date neslib? Try using the one at shiru's page instead.
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

first I'm using the neslib.s from his examples

ppu_on_all is defined as

Code: Select all

;void __fastcall__ ppu_on_all(void);

_ppu_on_all:
	lda <PPU_MASK_VAR
	ora #%00011000
ppu_onoff:
	sta <PPU_MASK_VAR
	sta PPU_MASK
	lda #$80
	sta PPU_CTRL
	jsr _ppu_waitnmi
	lda #$00
	sta PPU_ADDR
	sta PPU_ADDR
	lda <PPU_CTRL_VAR
	sta PPU_CTRL
	rts
I thought the chr banks may be getting switched. not sure why that is.
I agree my code is not the best, I'm struggling to find the best time/way to try and update the vram.
I experimented with the set_vram_update() function. and successfully wrote 16 bytes to the vram each frame with no glitches.

I need to test more. I want to update different spots of the name table(say 16 bytes for 8 different rows). That's 128 total bytes and 8 different calls to set_vram_update. What's the best way to get that done?

any better c libraries to use? or did you write your own library. I think I read you code in c.
:edit think I found the answer about libraries in another thread, and coltrane src
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 »

I think you need to redownload the examples, this is what ppu_on_all looks like when I just downloaded it now:

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
The problem with the old code that you seem to have is that writes #$80 to $2000 instead of the stuff that's stored in PPU_CTRL_VAR, forcing both sprites and nametable to use the $0000 page until the next frame's NMI. To me this looks like a bug that shiru has since corrected.


I've used cc65 a bit, and did prepare my own libraries work working with it. I don't have a tutorial or much in the way of examples to show. I've so far released one project publicly with full source, but I think you'll have an easier time with shiru's libs than trying to figure out my stuff. If you want to look, it's here: http://rainwarrior.ca/music/coltrane_src.zip
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

you were absolutely right about me using old libs. from june 2013. I got the new one from jan 2014. Then compiled the code from earlier, and still same behavior. I'm a beginner in 6502 so debugging is tough.

going to put a BP on 0x2000 and try to figure it out.

attached new compiled code incase anyone wants to take a look. no delay this try, compiled just as the pastie
Attachments
vram_write2.zip
(3.63 KiB) Downloaded 146 times
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 »

Just set bit 4 of the PPU_CTRL_VAR.
DrDementia
Posts: 32
Joined: Thu Oct 31, 2013 4:55 pm

Re: write to vram - in c problems

Post by DrDementia »

according to the wiki page you linked to bit 4 controls "Background pattern table address (0: $0000; 1: $1000)"

so couldn't I just use bank_bg(0); ? Can't seem to get that to work.
here's what that does.

Code: Select all

;void __fastcall__ bank_bg(unsigned char n);

_bank_bg:
	and #$01
	asl a
	asl a
	asl a
	asl a
	sta <TEMP
	lda <PPU_CTRL_VAR
	and #%11101111
	ora <TEMP
	sta <PPU_CTRL_VAR
	rts
edit: weird, what it does is : for a frame it thinks where I write the bytes to is the beginning of the nametable. or something ??? watching the nametable viewer in fceux shows this. not sure what it's doing.

edit2:
might be a bug in vram_write ??? if I comment that line out nothing strange happens. but it seems where I write to it thinks is the beginning of the NT or bank address??? and starting there that gets shown on screen. You can see it in the example I attached
Attachments
vram_write3.zip
(3.65 KiB) Downloaded 141 times
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 [url=http://forums.nesdev.com/viewtopic.php?p=127138#p127138]this post[/url], rainwarrior wrote:For an update that happens every frame, do not turn the PPU off
A little strong. Turning off rendering frees up the first 100 CPU cycles on the prerender scanline. I'd have said you usually don't need to.
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 »

You want bank_bg(1), your background tiles are at $1000.


I recommended not turning the PPU off because it is of no help when using this library, and turning the PPU back on here is not consequence free (especially since it seems to force scroll to 0,0 for the frame it is called on?). If you want to do advanced things by turning the PPU off, you're not going to be doing it with the library functions.

Actually, I'm surprised shiru didn't move the write to $2001 into the NMI instead; if ppu_on_all is called in the middle of the screen you're going to get a half rendered frame (with incorrect background scroll to boot), I think...
User avatar
Movax12
Posts: 529
Joined: Sun Jan 02, 2011 11:50 am

Re: write to vram - in c problems

Post by Movax12 »

rainwarrior wrote:I recommended not turning the PPU off ...turning the PPU back on here is not consequence free
I understood that forcing render off during vblank was a trick to gain a bit more time to write to VRAM. I turn it off almost immediately in NMI and don't turn it on until all PPU writes are done. Can you verify there are consequences? I'll change my code if there is a downside.

EDIT: Correction: "..don't turn it off until.." fixed.
Last edited by Movax12 on Mon Mar 24, 2014 7:54 pm, edited 1 time in total.
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 »

I'm referring specifically to the consequences of shiru's routine ppu_on_all, and only that. If you call it every frame you're going to get a visual problem.

If disabling rendering during vblank gives a performance boost I'd like to read more about it, actually, but I think it's a bit off topic in this thread. (I can't seem to find information about this on the wiki.)
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 »

rainwarrior wrote:If disabling rendering during vblank gives a performance boost I'd like to read more about it
There's no performance boost, you just get a little extra time for PPU memory accesses because the PPU itself won't be accessing memory during the pre-render scanline when rendering is off. Personally, I prefer to not disable rendering, but I wouldn't think twice about doing if I needed a few more dozen cycles of VBlank time.
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 »

Oh, so it's not really any different than the regular technique of keeping rendering off at the top of the screen, only where you happen to be turning back on? Okay. (Anyhow, sorry for the hijack.)
Post Reply