write to vram - in c problems
Moderator: Moderators
Re: write to vram - in c problems
[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.
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.
Re: write to vram - in c problems
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.
-
DrDementia
- Posts: 32
- Joined: Thu Oct 31, 2013 4:55 pm
Re: write to vram - in c problems
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.
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.
Re: write to vram - in c problems
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.DrDementia wrote:(making the screen scroll to where I write to)
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: write to vram - in c problems
The problem, I think, is with the implementation of ppu_on_all().
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:
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():
This adds an extra frame of latency to your turning off the PPU (probably negligible), but should hide the half-rendered frame.
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
rtsThe 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_ADDRThis 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()-
DrDementia
- Posts: 32
- Joined: Thu Oct 31, 2013 4:55 pm
Re: write to vram - in c problems
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?tokumaru wrote: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.DrDementia wrote:(making the screen scroll to where I write to)
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.
Re: write to vram - in c problems
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.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);
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.
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.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.
-
DrDementia
- Posts: 32
- Joined: Thu Oct 31, 2013 4:55 pm
Re: write to vram - in c problems
so looking at this pagetokumaru 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).
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
rtsCode: Select all
lda #$21
sta PPUADDR
lda #$08
sta PPUADDRhere $21,$08 are getting loaded into a and then stored to PPUADDR (upper byte first)
FCEUXD shows a,x,y but I didn't see the current vram address anywhere. might be there somewhere thoughtokumaru 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.
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: write to vram - in c problems
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
Re: write to vram - in c problems
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?
- rainwarrior
- Posts: 8062
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: write to vram - in c problems
They're all working fine for me in 2.2.2 so possibly it's been fixed?